initial commit
[rofl0r-KOL.git] / Kopie von Kol.pas
blob483769d042c50ee85c85a7c2497b004af9087ed6
1 //[START OF KOL.pas]
2 {****************************************************************
4 KKKKK KKKKK OOOOOOOOO LLLLL
5 KKKKK KKKKK OOOOOOOOOOOOO LLLLL
6 KKKKK KKKKK OOOOO OOOOO LLLLL
7 KKKKK KKKKK OOOOO OOOOO LLLLL
8 KKKKKKKKKK OOOOO OOOOO LLLLL
9 KKKKK KKKKK OOOOO OOOOO LLLLL
10 KKKKK KKKKK OOOOO OOOOO LLLLL
11 KKKKK KKKKK OOOOOOOOOOOOO LLLLLLLLLLLLL
12 KKKKK KKKKK OOOOOOOOO LLLLLLLLLLLLL
14 Key Objects Library (C) 2000 by Kladov Vladimir.
16 //[VERSION]
17 ****************************************************************
18 * VERSION 2.00
19 ****************************************************************
20 //[END OF VERSION]
22 K.O.L. - is a set of objects to create small programs
23 with the Delphi, but without the VCL. KOL allows to
24 create executables of size about 10 times smaller then
25 those created with the VCL. But this does not mean that
26 KOL is less power then the VCL - perhaps just the opposite...
28 KOL is provided free with the source code.
29 Copyright (C) Vladimir Kladov, 2000-2003.
31 For code provided by other developers (even if later
32 changed by me) authors are noted in the source.
34 mailto: bonanzas@online.sinor.ru
35 Web-Page: http://bonanzas.rinet.ru
37 See also Mirror Classes Kit (M.C.K.) which allows
38 to create KOL programs visually.
40 ****************************************************************}
42 //[UNIT DEFINES]
43 {$INCLUDE delphidef.inc}
45 //[START OF UNIT]
46 unit KOL;
47 {-}
49 Please note, that KOL does not use keyword 'class'. Instead,
50 poor Pascal 'object' is the base of our objects. So, remember,
51 how we worked earlier with such Object Pascal's objects:
52 |<br>
53 - to create objects dynamically, use P<objname> instead of
54 T<objname> to allocate a pointer for dynamically created
55 object instance;
56 |<br>
57 - remember, that constructors of objects can not be virtual.
58 Override procedure Init instead in your own derived objects;
59 |<br>
60 - rather then call constructors of objects, call global procedures
61 New<objname> (e.g. NewLabel). If not, first (for virtualally
62 created objects) call New( ); then call constructor Create
63 (which calls Init) - but this is possible only if the constructor
64 is overriden by a new one.
65 |<br>
66 - the operator 'is' is not applicable to objects. And operator 'as'
67 is not necessary (and is not applicable too), use typecast to desired
68 object type, e.g.: "PSomeObjectType( C )" inplace of "C as TSomeClassType".
69 |<br>
70 |<hr>
71 Also remember, that IF [ MyObj: PMyObj ] THEN
73 NOT[ with MyObj do ] BUT[ with MyObj^ do ]
75 Though it is possible to skip '^' symbol when accessing member
76 fields, methods, properties, e.g. [ MyObj.Execute; ]
77 |<hr>
78 |&U=&nbsp;&nbsp;&nbsp;<a href="#%0">%0</a><br>
79 |&B=<a href="%1.htm">%0</a><br>
80 |&C=<a href="%1.htm">%0</a>
81 | <table border=1 cellpadding=6 width=100%>
82 | <colgroup valign=top span=2>
83 | <tr>
84 | <td> objects </td> <td> functions by category </td>
85 | </tr>
86 | <td>
87 <C _TObj> <B TObj>
88 <C TList> <C TListEx> <C TStrList> <B TStrListEx>
89 <C TTree> <C TDirList> <C TIniFile> <C TCabFile>
90 <B TStream>
91 <B TControl>
92 <C TGraphicTool> <C TCanvas> <C TImageList> <C TIcon> <C TBitmap>
93 <C TGif> <C TGifDecoder> <B TJpeg>
94 <C TTimer> <C TThread> <C TTrayIcon> <C TDirChange> <B TMediaPlayer>
95 <C TMenu> <C TOpenSaveDialog> <C TOpenDirDialog> <B TColorDialog>
96 <C TAction> <B TActionList>
97 <B Exception>
98 | </td>
99 | <td>
100 |<a href="kol_pas.htm#visual_objects_constructors">
101 Visual objects constructing functions
102 |</a><br><br>
103 <U Working with null-terminated and ansi strings>
104 <U Small bit arrays (max 32 bits in array)>
105 <U Arithmetics, geometry and other utility functions>
106 <U Data sorting (quicksort implementation)>
107 <U String to number and number to string conversions>
108 <U 64-bit integer numbers>
109 <U Floating point numbers>
110 <U Date and time handling>
111 <U File and directory routines>
112 <U System functions and working with windows>
113 <U Text in clipboard operations>
114 <U Wrappers to registry API functions>
115 | </td>
116 | </table>
118 Several conditional symbols can be used in a project
119 (Project | Options | Directories/Conditional Defines)
120 to change code generated a bit. There are following:
121 |<pre>
123 PAS_VERSION - to use Pascal version of the code.
124 PARANOIA - to force short versions of asm instructions (for D5
125 and below, D6 and higher use those instructions always).
126 USE_CONSTRUCTORS - to use constructors like in VCL.
127 USE_CUSTOMEXTENSIONS - to extend TControl with custom additions.
128 UNICODE_CTRLS - to use Unicode versions of controls (WM_XXXXW messages,
129 etc.)
130 USE_MHTOOLTIP - to use MHTOOLTIP.
131 NOT_USE_OnIdle - to stop using OnIdle event (to make code smaller
132 if it is not used actually).
133 USE_ASM_DODRAG - to use assembler version of code for DoDrag.
134 ENUM_DYN_HANDLERS_AFTER_RUN - to allow all the events handling even when
135 AppletTerminated become TRUE.
136 ALL_BUTTONS_RESPOND_TO_ENTER - obvious (by default, buttons respond to key
137 SPACE, since those are working this way in Windows).
138 ESC_CLOSE_DIALOGS - to allow closing all dialogs with ESCAPE.
139 OpenSaveDialog_Extended - to allow using custom extensions for OpenSaveDialog.
140 AUTO_CONTEXT_HELP - to use automatic respond to WM_CONTEXTMENU to call
141 context help.
142 NOT_FIX_CURINDEX - to use old version of TControl.SetItems, which could
143 lead to loose CurIndex value (e.g. for Combobox)
144 NEW_MODAL - to use extended madalness.
145 USE_SETMODALRESULT - to guarantee ModalResult property assigninig handling.
146 USE_MENU_CURCTL - to use CurCtl property in popup menu to detect which
147 control initiated a pop-up.
148 NEW_MENU_ACCELL - to use another menu accelerators handling, without
149 AcceleratorTable
150 USE_DROPDOWNCOUNT - to force setting combobox dropdown count.
151 NOT_UNLOAD_RICHEDITLIB - to stop unload Rich Edit library in finalization
152 section (to economy several byte of code).
153 DEBUG_GDIOBJECTS - to allow counting all the GDI objects used.
154 CHK_BITBLT - to check BitBlt operations.
155 DEBUG_ENDSESSION - to allow debugging WM_ENDSESSION handling.
156 DEBUG_CREATEWINDOW - to debug CreateWindow.
157 TEST_CLOSE - to debug Close.
158 DEBUG_MENU - to debug menu.
159 DEBUG_DBLBUFF - to debug DoubleBuffered.
160 DEBUG - other debugging.
162 |</pre>
164 {= K.O.L - êëþ÷åâàÿ áèáëèîòåêà îáúåêòîâ. (C) Êëàäîâ Âëàäèìèð, 2000-2003.
167 //[OPTIONS]
168 {$A-} // align off, otherwise code is not good
171 {$Q-} // no overflow check: this option makes code wrong
172 {$R-} // no range checking: this option makes code wrong
173 {$T-} // not typed @-operator
174 //{$D+}
175 {$IFDEF INPACKAGE} // use this symbol in packages requiring kol.pas
176 {$WARNINGS OFF}
177 {$ENDIF}
178 {$IFDEF _D7orHigher}
179 {$WARN UNSAFE_TYPE OFF} // Too many such warnings in Delphi7
180 {$WARN UNSAFE_CODE OFF}
181 {$WARN UNSAFE_CAST OFF}
182 {$ENDIF}
185 //[START OF INTERFACE]
186 interface
188 //{$DEFINE DEBUG_GDIOBJECTS}
189 //{$DEFINE CHK_GDI}
191 //[USES]
192 uses
193 messages, windows, RichEdit {$IFDEF CHK_GDI}, ChkGdi {$ENDIF};
194 //[END OF USES]
196 {$IFDEF DEBUG_GDIOBJECTS}
198 BrushCount: Integer;
199 FontCount: Integer;
200 PenCount: Integer;
201 {$ENDIF}
204 //{_#IF [DELPHI]}
205 {$INCLUDE delphicommctrl.inc}
206 //{_#ENDIF}
208 type
209 //[_TObj DEFINITION]
212 _TObj = object
213 {* auxiliary object type. See TObj. }
214 protected
215 procedure Init; virtual;
216 {* Is called from a constructor to initialize created object instance
217 filling its fields with 0. Can be overriden in descendant objects
218 to add another initialization code there. (Main reason of intending
219 is what constructors can not be virtual in poor objects). }
220 {= Âûçûâàåòñÿ äëÿ èíèöèàëèçàöèè îáúåêòà. }
221 public
222 function VmtAddr: Pointer;
223 {* Returns addres of virtual methods table of object. ? }
224 {= âîçâðàùàåò àäðåñ òàáëèöû âèðòóàëüíûõ ìåòîäîâ (VMT). ? }
225 end;
228 {++}(* TObj = class;*){--}
229 PObj = {-}^{+}TObj;
230 {* }
232 {++}(* TList = class;*){--}
233 PList = {-}^{+}TList;
234 {* }
236 //[TObjectMethod DECLARATION]
237 TObjectMethod = procedure of object;
238 {* }
239 TOnEvent = procedure( Sender: PObj ) of object;
240 {* This type of event is the most common - event handler when called can
241 know only what object was a sender of this call. Replaces good known
242 VCL TNotifyEvent event type. }
244 //[TPointerList DECLARATION]
245 PPointerList = ^TPointerList;
246 TPointerList = array[0..MaxInt div 4 - 1] of Pointer;
248 { ---------------------------------------------------------------------
250 TObj - base object to derive all others
252 ---------------------------------------------------------------------- }
253 //[TObj DEFINITION]
254 TObj = {-} object( _TObj ) {+}{++}(*class*){--}
255 {* Prototype for all objects of KOL. All its methods are important to
256 implement objects in a manner similar to Delphi TObject class. }
257 {= Áàçîâûé êëàññ äëÿ âñåõ ïðî÷èõ îáúåêòîâ KOL. }
258 protected
259 fRefCount: Integer;
260 fOnDestroy: TOnEvent;
261 procedure DoDestroy;
262 protected
263 fAutoFree: PList;
264 {* Is called from a constructor to initialize created object instance
265 filling its fields with 0. Can be overriden in descendant objects
266 to add another initialization code there. (Main reason of intending
267 is what constructors can not be virtual in poor objects). }
268 {= Âûçûâàåòñÿ äëÿ èíèöèàëèçàöèè îáúåêòà. }
269 fTag: DWORD;
270 {* Custom data. }
271 {++}(*public*){--}
272 destructor Destroy; {-} virtual; {+}{++}(* override; *){--}
273 {* Disposes memory, allocated to an object. Does not release huge strings,
274 dynamic arrays and so on. Such memory should be freeing in overriden
275 destructor. }
276 {= Îñâîáîæäàåò ïàìÿòü, âûäåëåííóþ äëÿ îáúåêòà. Íå îñâîáîæäàåò ïàìÿòü, âûäåëåííóþ
277 äëÿ ñòðîê, äèíàìè÷èñêèõ ìàññèâîâ è ò.ï. Òàêàÿ ïàìÿòü äîëæíà áûòü îñâîáîæäåíà
278 â ïåðåîïðåäåëåííîì äåñòðóêòîðå îáúåêòà. }
279 {++}(*protected*){--}
280 {++}(*
281 procedure Init; virtual;
282 {* Can be overriden in descendant objects
283 to add initialization code there. (Main reason of intending
284 is what constructors can not be virtual in poor objects). }
285 *){--}
286 procedure Final;
287 {* Is called in destructor to perform OnDestroy event call and to
288 released objects, added to fAutoFree list. }
289 public
290 procedure Free;
291 {* Before calling destructor of object, checks if passed pointer is not
292 nil - similar what is done in VCL for TObject. It is ALWAYS recommended
293 to use Free instead of Destroy - see also comments to RefInc, RefDec. }
294 {= Äî âûçîâà äåñòðóêòîðà, ïðîâåðÿåò, íå ïåðåäàí ëè nil â êà÷åñòâå ïàðàìåòðà.
295 ÂÑÅÃÄÀ ðåêîìåíäóåòñÿ èñïîëüçîâàòü Free âìåñòî Destroy - ñì. òàê æå RefInc,
296 RefDec. }
299 // By Vyacheslav Gavrik:
300 function InstanceSize: Integer;
301 {* Returns a size of object instance. }
304 constructor Create;
305 {* Constructor. Do not call it. Instead, use New<objectname> function
306 call for certain object, e.g., NewLabel( AParent, 'caption' ); }
307 {= Êîíñòðóêòîð. Íå ñëåäóåò âûçûâàòü åãî. Äëÿ êîíñòðóèðîâàíèÿ îáúåêòîâ,
308 âûçûâàéòå ñîîòâåòñòâóþùóþ ãëîáàëüíóþ ôóíêöèþ New<èìÿ-îáúåêòà>. Íàïðèìåð,
309 NewLabel( MyForm, 'Ìåòêà¹1' ); }
311 class function AncestorOfObject( Obj: Pointer ): Boolean;
312 {* Is intended to replace 'is' operator, which is not applicable to objects. }
313 {= }
314 function VmtAddr: Pointer;
315 {* Returns addres of virtual methods table of object. }
316 {= âîçâðàùàåò àëðåñ òàáëèöû âèðòóàëüíûõ ìåòîäîâ (VMT). }
318 procedure RefInc;
319 {* See comments below. }
320 {= Ñì. RefDec íèæå. }
321 procedure RefDec;
322 {* Decrements reference count. If it is becoming <0, and Free
323 method was already called, object is (self-) destroyed. Otherwise,
324 Free method does not destroy object, but only sets flag
325 "Free was called".
326 |<br>
327 Use RefInc..RefDec to provide a block of code, where
328 object can not be destroyed by call of Free method.
329 This makes code more safe from intersecting flows of processing,
330 where some code want to destroy object, but others suppose that it
331 is yet existing.
332 |<br>
333 If You want to release object at the end of block RefInc..RefDec,
334 do it immediately BEFORE call of last RefDec (to avoid situation,
335 when object is released in result of RefDec, and attempt to
336 destroy it follow leads to AV exception).
338 {= Óìåíüøàåò ñ÷åò÷èê èñïîëüçîâàíèÿ. Åñëè â ðåçóëüòàòå ñ÷åò÷èê ñòàíîâèòñÿ
339 < 0, è ìåòîä Free óæå áûë âûçâàí, îáúåêò (ñàìî-) ðàçðóøàåòñÿ. Èíà÷å,
340 ìåòîä Free íå ðàçðóøàåò îáúåêò, à òîëüêî óñòàíàâëèâàåò ôëàã "Free áûë
341 âûçâàí".
342 |<br>
343 Èñïîëüçóéòå RefInc..RefDec äëÿ ïðåäîòâðàùåíèÿ ðàçðóøåíèÿ îáúåêòà íà
344 íåêîòîðîì ó÷àñòêå êîäà (åñëè åñòü òàêàÿ íåîáõîäèìîñòü).
345 |<br>
346 Åñëè íóæíî óáèòü (âðåìåííûé) îáúåêò âìåñòå ñ ïîñëåäíèì RefDec, ñäåëàéòå
347 âûçîâ Free íåìåäëåííî ÏÅÐÅÄ ïîñëåäíèì RefDec. }
348 property RefCount: Integer read fRefCount;
349 {* }
350 property OnDestroy: TOnEvent read fOnDestroy write fOnDestroy;
351 {* This event is provided for any KOL object, so You can provide your own
352 OnDestroy event for it. }
353 {= Äàííîå ñîáûòèå îáåñïå÷èâàåòñÿ äëÿ âñåõ îáúåêòîâ KOL. Ïîçâîëÿåò ñäåëàòü
354 ÷òî-íèáóäü â ñâÿçè ñ ðàçðóøåíèåì îáúåêòà. }
355 procedure Add2AutoFree( Obj: PObj );
356 {* Adds an object to the list of objects, destroyed automatically
357 when the object is destroyed. Do not add here child controls of
358 the TControl (these are destroyed by another way). Only non-control
359 objects, which are not destroyed automatically, should be added here. }
360 procedure Add2AutoFreeEx( Proc: TObjectMethod );
361 {* Adds an event handler to the list of events, called in destructor.
362 This method is mainly for internal use, and allows to auto-destroy
363 VCL components, located on KOL form at design time (in MCK project). }
364 property Tag: DWORD read fTag write fTag;
365 {* Custom data field. }
366 end;
367 //[END OF TObj DEFINITION]
369 { ---------------------------------------------------------------------
371 TList - object to implement list of pointers (or dwords)
373 ---------------------------------------------------------------------- }
374 //[TList DEFINITION]
375 TList = object( TObj )
376 {* Simple list of pointers. It is used in KOL instead of standard VCL
377 TList to store any kind data (or pointers to these ones). Can be created
378 calling function NewList. }
379 {= Ïðîñòîé ñïèñîê óêàçàòåëåé. }
380 protected
381 fItems: PPointerList;
382 fCount: Integer;
383 fCapacity: Integer;
384 fAddBy: Integer;
385 procedure SetCount(const Value: Integer);
386 procedure SetAddBy(Value: Integer);
387 {++}(*public*){--}
388 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
389 {* Destroys list, freeing memory, allocated for pointers. Programmer
390 is resposible for destroying of data, referenced by the pointers. }
391 {= }
392 {++}(*protected*){--}
393 procedure SetCapacity( Value: Integer );
394 function Get( Idx: Integer ): Pointer;
395 procedure Put( Idx: Integer; Value: Pointer );
396 {$IFDEF USE_CONSTRUCTORS}
397 procedure Init; virtual;
398 {$ENDIF USE_CONSTRUCTORS}
399 public
400 procedure Clear;
401 {* Makes Count equal to 0. Not responsible for freeing (or destroying)
402 data, referenced by released pointers. }
403 procedure Add( Value: Pointer );
404 {* Adds pointer to the end of list, increasing Count by one. }
405 procedure Insert( Idx: Integer; Value: Pointer );
406 {* Inserts pointer before given item. Returns Idx, i.e. index of
407 inserted item in the list. Indeces of items, located after insertion
408 point, are increasing. To add item to the end of list, pass Count
409 as index parameter. To insert item before first item, pass 0 there. }
410 function IndexOf( Value: Pointer ): Integer;
411 {* Searches first (from start) item pointer with given value and returns
412 its index (zero-based) if found. If not found, returns -1. }
413 procedure Delete( Idx: Integer );
414 {* Deletes given (by index) pointer item from the list, shifting all
415 follow item indeces up by one. }
416 procedure DeleteRange( Idx, Len: Integer );
417 {* Deletes Len items starting from Idx. }
418 procedure Remove( Value: Pointer );
419 {* Removes first entry of a Value in the list. }
420 property Count: Integer read fCount write SetCount;
421 {* Returns count of items in the list. It is possible to delete a number
422 of items at the end of the list, keeping only first Count items alive,
423 assigning new value to Count property (less then Count it is). }
424 property Capacity: Integer read fCapacity write SetCapacity;
425 {* Returns number of pointers which could be stored in the list
426 without reallocating of memory. It is possible change this value
427 for optimize usage of the list (for minimize number of reallocating
428 memory operations). }
429 property Items[ Idx: Integer ]: Pointer read Get write Put; default;
430 {* Provides access (read and write) to items of the list. Please note,
431 that TList is not responsible for freeing memory, referenced by stored
432 pointers. }
433 function Last: Pointer;
434 {* Returns the last item (or nil, if the list is empty). }
435 procedure Swap( Idx1, Idx2: Integer );
436 {* Swaps two items in list directly (fast, but without testing of
437 index bounds). }
438 procedure MoveItem( OldIdx, NewIdx: Integer );
439 {* Moves item to new position. Pass NewIdx >= Count to move item
440 after the last one. }
441 procedure Release;
442 {* Especially for lists of pointers to dynamically allocated memory.
443 Releases all pointed memory blocks and destroys object itself. }
444 procedure ReleaseObjects;
445 {* Especially for a list of objects derived from TObj.
446 Calls Free for every of the object in the list, and then calls
447 Free for the object itself. }
448 property AddBy: Integer read fAddBy write SetAddBy;
449 {* Value to increment capacity when new items are added or inserted
450 and capacity need to be increased. }
451 property DataMemory: PPointerList read fItems;
452 {* Raw data memory. Can be used for direct access to items of a list. }
453 procedure Assign( SrcList: PList );
454 {* Copies all source list items. }
455 end;
456 //[END OF TList DEFINITION]
458 //[NewList DECLARATION]
459 function NewList: PList;
460 {* Returns pointer to newly created TList object. Use it instead usual
461 TList.Create as it is done in VCL or XCL. }
463 procedure FastIncNum2Elements( List: TList; FromIdx, Count, Value: Integer );
464 {* Very fast adds Value to List elements from List[FromIdx] to List[FromIdx+Count-1].
465 Given elements must exist. Count must be > 0. }
467 procedure Free_And_Nil( var Obj );
468 {* Obj.Free and Obj := nil, where Obj *MUST* be TObj or its descendant
469 (TControl, TMenu, etc.) This procedure is not compatible with VCL's
470 FreeAndNil, which works with TObject, since this it has another name. }
472 type
474 //[TListEx DEFINITION]
475 {++}(*TListEx = class;*){--}
476 PListEx = {-}^{+}TListEx;
477 TListEx = object( TObj )
478 {* Extended list, with Objects[ ] property. Created calling NewListEx function. }
479 protected
480 fList: PList;
481 fObjects: PList;
482 function GetEx(Idx: Integer): Pointer;
483 procedure PutEx(Idx: Integer; const Value: Pointer);
484 function GetCount: Integer;
485 function GetAddBy: Integer;
486 procedure Set_AddBy(const Value: Integer);
487 public
488 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
489 {* }
490 property AddBy: Integer read GetAddBy write Set_AddBy;
491 {* }
492 property Items[ Idx: Integer ]: Pointer read GetEx write PutEx;
493 {* }
494 property Count: Integer read GetCount;
495 {* }
496 procedure Clear;
497 {* }
498 procedure Add( Value: Pointer );
499 {* }
500 procedure AddObj( Value, Obj: Pointer );
501 {* }
502 procedure Insert( Idx: Integer; Value: Pointer );
503 {* }
504 procedure InsertObj( Idx: Integer; Value, Obj: Pointer );
505 {* }
506 procedure Delete( Idx: Integer );
507 {* }
508 procedure DeleteRange( Idx, Len: Integer );
509 {* }
510 function IndexOf( Value: Pointer ): Integer;
511 {* }
512 function IndexOfObj( Obj: Pointer ): Integer;
513 {* }
514 procedure Swap( Idx1, Idx2: Integer );
515 {* }
516 procedure MoveItem( OldIdx, NewIdx: Integer );
517 {* }
518 property ItemsList: PList read fList;
519 {* }
520 property ObjList: PList read fObjects;
521 {* }
522 function Last: Pointer;
523 {* }
524 function LastObj: Pointer;
525 {* }
526 end;
527 //[END OF TListEx DEFINITION]
529 //[NewListEx DECLARATION]
530 function NewListEx: PListEx;
531 {* Creates extended list. }
539 { -- tree (non-visual) -- }
541 type
542 //[TTree DEFINITION]
543 {++}(*TTree = class;*){--}
544 PTree = {-}^{+}TTree;
545 TTree = object( TObj )
546 {* Object to store tree-like data in memory (non-visual). }
547 protected
548 fParent: PTree;
549 fChildren: PList;
550 fPrev: PTree;
551 fNext: PTree;
552 fName: String;
553 fData: Pointer;
554 function GetCount: Integer;
555 function GetItems(Idx: Integer): PTree;
556 procedure Unlink;
557 function GetRoot: PTree;
558 function GetLevel: Integer;
559 function GetTotal: Integer;
560 function GetIndexAmongSiblings: Integer;
561 protected
562 {$IFDEF USE_CONSTRUCTORS}
563 constructor CreateTree( AParent: PTree; const AName: String );
564 {* }
565 {$ENDIF}
566 {++}(*public*){--}
567 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
568 {* }
569 {++}(*protected*){--}
570 procedure Init; {-}virtual;{+}{++}(*override;*){--}
571 public
572 procedure Clear;
573 {* Destoyes all child nodes. }
574 property Name: String read fName write fName;
575 {* Optional node name. }
576 property Data: Pointer read fData write fData;
577 {* Optional user-defined pointer. }
578 property Count: Integer read GetCount;
579 {* Number of child nodes of given node. }
580 property Items[ Idx: Integer ]: PTree read GetItems;
581 {* Child nodes list items. }
582 procedure Add( Node: PTree );
583 {* Adds another node as a child of given tree node. This operation
584 as well as Insert can be used to move node together with its children
585 to another location of the same tree or even from another tree.
586 Anyway, added Node first correctly removed from old place (if it is
587 defined for it). But for simplest task, such as filling of tree with
588 nodes, code should looking as follows:
589 ! Node := NewTree( nil, 'test of creating node without parent' );
590 ! RootOfMyTree.Add( Node );
591 Though, this code gives the same result as:
592 ! Node := NewTree( RootOfMyTree, 'test of creatign node as a child' ); }
593 procedure Insert( Before, Node: PTree );
594 {* Inserts earlier created 'Node' just before given child node 'Before'
595 as a child of given tree node. See also Add method. }
596 property Parent: PTree read fParent;
597 {* Returns parent node (or nil, if there is no parent). }
598 property Index: Integer read GetIndexAmongSiblings;
599 {* Returns an index of the node in a list of nodes of the same parent
600 (or -1, if Parent is not defined). }
601 property PrevSibling: PTree read fPrev;
602 {* Returns previous node in a list of children of the Parent. Nil is
603 returned, if given node is the first child of the Parent or has
604 no Parent. }
605 property NextSibling: PTree read fNext;
606 {* Returns next node in a list of children of the Parent. Nil is returned,
607 if given node is the last child of the Parent or has no Parent at all. }
608 property Root: PTree read GetRoot;
609 {* Returns root node (i.e. the last Parent, enumerating parents recursively). }
610 property Level: Integer read GetLevel;
611 {* Returns level of the node, i.e. integer value, equal to 0 for root
612 of a tree, 1 for its children, etc. }
613 property Total: Integer read GetTotal;
614 {* Returns total number of children of the node and all its children
615 counting its recursively (but node itself is not considered, i.e.
616 Total for node without children is equal to 0). }
617 procedure SortByName;
618 {* Sorts children of the node in ascending order. Sorting is not
619 recursive, i.e. only immediate children are sorted. }
620 procedure SwapNodes( i1, i2: Integer );
621 {* Swaps two child nodes. }
622 function IsParentOfNode( Node: PTree ): Boolean;
623 {* Returns true, if Node is the tree itself or is a parent of the given node
624 on any level. }
625 function IndexOf( Node: PTree ): Integer;
626 {* Total index of the child node (on any level under this node). }
628 end;
629 //[END OF TTree DEFINITION]
631 //[NewTree DECLARATION]
632 function NewTree( AParent: PTree; const AName: String ): PTree;
633 {* Constructs tree node, adding it to the end of children list of
634 the AParent. If AParent is nil, new root tree node is created. }
642 //[DummyObjProc, DummyObjProcParam DECLARATION]
643 procedure DummyObjProc( Sender: PObj );
644 procedure DummyObjProcParam( Sender: PObj; Param: Pointer );
649 { --- threads --- }
650 //[THREADS]
652 const
653 ABOVE_NORMAL_PRIORITY_CLASS = $8000; // only for Windows 2K
654 BELOW_NORMAL_PRIORITY_CLASS = $4000; // and higher !
656 type
657 {++}(*TThread = class;*){--}
658 PThread = {-}^{+}TThread;
660 TThreadMethod = procedure of object;
661 TThreadMethodEx = procedure( Sender: PThread; Param: Pointer ) of object;
663 TOnThreadExecute = function(Sender:PThread): Integer of object;
664 {* Event to be called when Execute method is called for TThread }
666 { ---------------------------------------------------------------------
668 TThread object
670 ---------------------------------------------------------------------- }
671 //[TThread DEFINITION]
672 TThread = object(TObj)
673 {* Thread object. It is possible not to derive Your own thread-based
674 object, but instead create thread Suspended and assign event
675 OnExecute. To create, use one of NewThread of NewThreadEx functions,
676 or derive Your own descendant object and write creation function
677 (or constructor) for it.
678 |<br><br>
679 Aknowledgements. Originally class ZThread was developed for XCL:
680 |<br> * By: Tim Slusher : junior@nlcomm.com
681 |<br> * Home: http://www.nlcomm.com/~junior
683 protected
684 FSuspended,
685 FTerminated: boolean;
686 FHandle: THandle;
687 FThreadId: DWORD;
688 FOnSuspend: TObjectMethod;
689 FOnResume: TOnEvent;
690 FData : Pointer;
691 FOnExecute : TOnThreadExecute;
692 FMethod: TThreadMethod;
693 FMethodEx: TThreadMethodEx;
694 F_AutoFree: Boolean;
695 function GetPriorityCls: Integer;
696 function GetThrdPriority: Integer;
697 procedure SetPriorityCls(Value: Integer);
698 procedure SetThrdPriority(Value: Integer);
699 {++}(*public*){--}
700 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
701 {* }
702 public
703 function Execute: integer; virtual;
704 {* Executes thread. Do not call this method from another thread! (Even do
705 not call this method at all!) Instead, use Resume.
706 |<br>
707 Note also that in contrast to VCL, it is not necessary to create your
708 own descendant object from TThread and override Execute method. In KOL,
709 it is sufficient to create an instance of TThread object (see NewThread,
710 NewThreadEx, NewThreadAutoFree functions) and assign OnExecute event
711 handler for it. }
712 procedure Resume;
713 {* Continues executing. It is necessary to make call for every
714 nested Suspend. }
715 procedure Suspend;
716 {* Suspends thread until it will be resumed. Can be called from another
717 thread or from the thread itself. }
718 procedure Terminate;
719 {* Terminates thread. }
720 function WaitFor: Integer;
721 {* Waits (infinitively) until thead will be finished. }
723 property Handle: THandle read FHandle;
724 {* Thread handle. It is created immediately when object is created
725 (using NewThread). }
726 property Suspended: boolean read FSuspended;
727 {* True, if suspended. }
728 property Terminated: boolean read FTerminated;
729 {* True, if terminated. }
730 property ThreadId: DWORD read FThreadId;
731 {* Thread id. }
732 property PriorityClass: Integer read GetPriorityCls write SetPriorityCls;
733 {* Thread priority class. One of following values: HIGH_PRIORITY_CLASS,
734 IDLE_PRIORITY_CLASS, NORMAL_PRIORITY_CLASS, REALTIME_PRIORITY_CLASS. }
735 property ThreadPriority: Integer read GetThrdPriority write SetThrdPriority;
736 {* Thread priority value. One of following values: THREAD_PRIORITY_ABOVE_NORMAL,
737 THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_IDLE,
738 THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_TIME_CRITICAL. }
739 property Data : Pointer read FData write FData;
740 {* Custom data pointer. Use it for Youe own purpose. }
742 property OnExecute: TOnThreadExecute read FOnExecute write FOnExecute;
743 {* Is called, when Execute is starting. }
744 property OnSuspend: TObjectMethod read FOnSuspend write FOnSuspend;
745 {* Is called, when Suspend is performed. }
746 property OnResume: TOnEvent read FOnResume write FOnResume;
747 {* Is called, when resumed. }
748 procedure Synchronize( Method: TThreadMethod );
749 {* Call it to execute given method in main thread context. Applet variable
750 must exist for that time. }
751 procedure SynchronizeEx( Method: TThreadMethodEx; Param: Pointer );
752 {* Call it to execute given method in main thread context, with a given
753 parameter. Applet variable must exist for that time. Param must not be nil. }
754 {$IFDEF USE_CONSTRUCTORS}
755 constructor ThreadCreate;
756 constructor ThreadCreateEx( const Proc: TOnThreadExecute );
757 {$ENDIF USE_CONSTRUCTORS}
759 property AutoFree: Boolean read F_AutoFree write F_AutoFree;
760 {* Set this property to true to provide automatic destroying of thread
761 object when its executing is finished. }
762 end;
763 //[END OF TThread DEFINITION]
765 //[NewThread, NewThreadEx, NewThreadAutoFree, Global_Synchronized DECLARATIONS]
766 function NewThread: PThread;
767 {* Creates thread object (always suspended). After creating, set event
768 OnExecute and perform Resume operation. }
770 function NewThreadEx( const Proc: TOnThreadExecute ): PThread;
771 {* Creates thread object, assigns Proc to its OnExecute event and runs
772 it. }
774 function NewThreadAutoFree( const Proc: TOnThreadExecute ): PThread;
775 {* Creates thread object similar to NewThreadEx, but freeing automatically
776 when executing of such thread finished. Be sure that a thread is resumed
777 at least to provide its object keeper freeing. }
779 var Global_Synchronized: procedure( Sender: PObj; Param: Pointer ) = DummyObjProcParam;
780 // It is not necessary to declare it as threadvar.
795 { -- streams -- }
796 //[STREAMS]
798 type
799 TMoveMethod = ( spBegin, spCurrent, spEnd );
801 {++}(*TStream = class;*){--}
802 PStream = {-}^{+}TStream;
804 PStreamMethods = ^TStreamMethods;
805 TStreamMethods = Packed Record
806 fSeek: function( Strm: PStream; MoveTo: Integer; MoveMethod: TMoveMethod ): DWORD;
807 fGetSiz: function( Strm: PStream ): DWORD;
808 fSetSiz: procedure( Strm: PStream; Value: DWORD );
809 fRead: function( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
810 fWrite: function( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
811 fClose: procedure( Strm: PStream );
812 fCustom: Pointer;
813 fWait: procedure( Strm: PStream );
814 end;
816 TStreamData = Packed Record
817 fHandle: THandle;
818 fCapacity, fSize, fPosition: DWORD;
819 fThread: PThread;
820 end;
822 { ---------------------------------------------------------------------
824 TStream - streaming objects incapsulation
826 ---------------------------------------------------------------------- }
827 //[TStream DEFINITION]
828 TStream = object(TObj)
829 {* Simple stream object. Can be opened for file, or as memory stream (see
830 NewReadFileStream, NewWriteFileStream, NewMemoryStream, etc.). And, another
831 type of streaming object can be derived (without inheriting new object
832 type, just by writing another New...Stream method, which calls
833 _NewStream and pass methods record to it). }
834 protected
835 fPMethods: PStreamMethods;
836 fMethods: TStreamMethods;
837 fMemory: Pointer;
838 fData: TStreamData;
839 fParam1, fParam2: DWORD; // parameters to use in thread
840 function GetCapacity: DWORD;
841 procedure SetCapacity(const Value: DWORD);
842 function DoAsyncRead( Sender: PThread ): Integer;
843 function DoAsyncWrite( Sender: PThread ): Integer;
844 function DoAsyncSeek( Sender: PThread ): Integer;
845 protected
846 function GetFileStreamHandle: THandle;
847 procedure SetPosition(Value: DWord);
848 function GetPosition: DWord;
849 function GetSize: DWord;
850 procedure SetSize(NewSize: DWord);
851 {++}(*public*){--}
852 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
853 public
854 function Read(var Buffer; Count: DWord): DWord;
855 {* Reads Count bytes from a stream. Returns number of bytes read. }
856 function Seek(MoveTo: Integer; MoveMethod: TMoveMethod): DWord;
857 {* Allows to change current position or to obtain it. Property
858 Position uses this method both for get and set position. }
859 function Write(var Buffer; Count: DWord): DWord;
860 {* Writes Count bytes from Buffer, starting from current position
861 in a stream. Returns how much bytes are written. }
862 function WriteStr( S: String ): DWORD;
863 {* Writes string to the stream, not including ending #0. Exactly
864 Length( S ) characters are written. }
865 function WriteStrZ( S: String ): DWORD;
866 {* Writes string, adding #0. Number of bytes written is returned. }
867 function ReadStrZ: String;
868 {* Reads string, finished by #0. After reading, current position in
869 the stream is set to the byte, follows #0. }
870 function ReadStr: String;
871 {* Reads string, finished by #13, #10 or #13#10 symbols. Terminating symbols
872 #13 and/or #10 are not added to the end of returned string though
873 stream positioned follow it. }
874 function WriteStrEx(S: String): DWord;
875 {* Writes string S to stream, also saving its size for future use by
876 ReadStrEx* functions. Returns number of actually written characters. }
877 function ReadStrExVar(var S: String): DWord;
878 {* Reads string from stream and assigns it to S.
879 Returns number of actually read characters.
880 Note:
881 String must be written by using WriteStrEx function.
882 Return value is count of characters READ, not the length of string. }
883 function ReadStrEx: String;
884 {* Reads string from stream and returns it. }
885 function WriteStrPas( S: String ): DWORD;
886 {* Writes a string in Pascal short string format - 1 byte length, then string
887 itself without trailing #0 char. S parameter length should not exceed 255
888 chars, rest chars are truncated while writing. Total amount of bytes
889 written is returned. }
890 function ReadStrPas: String;
891 {* Reads 1 byte from a stream, then treat it as a length of following string
892 which is read and returned. A purpose of this function is reading strings
893 written using WriteStrPas. }
894 property Size: DWord read GetSize write SetSize;
895 {* Returns stream size. For some custom streams, can be slow
896 operation, or even always return undefined value (-1 recommended). }
897 property Position: DWord read GetPosition write SetPosition;
898 {* Current position. }
900 property Memory: Pointer read fMemory;
901 {* Only for memory stream. }
902 property Handle: THandle read GetFileStreamHandle;
903 {* Only for file stream. It is possible to check that Handle <>
904 INVALID_HANDLE_VALUE to ensure that file stream is created OK. }
906 //---------- for asynchronous operations (using thread - not tested):
907 procedure SeekAsync(MoveTo: Integer; MoveMethod: TMoveMethod);
908 {* Changes current position asynchronously. To wait for finishing the
909 operation, use method Wait. }
910 procedure ReadAsync(var Buffer; Count: DWord);
911 {* Reads Count bytes from a stream asynchronously. To wait finishing the
912 operation, use method Wait. }
913 procedure WriteAsync(var Buffer; Count: DWord);
914 {* Writes Count bytes from Buffer, starting from current position
915 in a stream - asynchronously. To wait finishing the operation,
916 use method Wait. }
917 function Busy: Boolean;
918 {* Returns TRUE until finishing the last asynchronous operation
919 started by calling SeekAsync, ReadAsync, WriteAsync methods. }
920 procedure Wait;
921 {* Waits for finishing the last asynchronous operation. }
923 property Methods: PStreamMethods read fPMethods;
924 {* Pointer to TStreamMethods record. Useful to implement custom-defined
925 streams, which can access its fCustom field, or even to change
926 methods when necessary. }
927 property Data: TStreamData read fData;
928 {* Pointer to TStreamData record. Useful to implement custom-defined
929 streams, which can access Data fields directly when implemented. }
931 property Capacity: DWORD read GetCapacity write SetCapacity;
932 {* Amound of memory allocated for data (MemoryStream). }
934 end;
935 //[END OF TStream DEFINITION]
937 //[_NewStream DECLARATION]
938 function _NewStream( const StreamMethods: TStreamMethods ): PStream;
939 {* Use this method only to define your own stream type. See also declared
940 below (in KOL.pas) methods used to implement standard KOL streams. You can use it in
941 your code to create streams, which are partially based on standard
942 methods. }
944 // Methods below are declared here to simplify creating your
945 // own streams with some methods standard and some non-standard
946 // together:
947 function SeekFileStream( Strm: PStream; MoveTo: Integer; MoveFrom: TMoveMethod ): DWORD;
948 function GetSizeFileStream( Strm: PStream ): DWORD;
949 function ReadFileStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
950 function WriteFileStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
951 function WriteFileStreamEOF( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
952 procedure CloseFileStream( Strm: PStream );
953 function SeekMemStream( Strm: PStream; MoveTo: Integer; MoveFrom: TMoveMethod ): DWORD;
954 function GetSizeMemStream( Strm: PStream ): DWORD;
955 procedure SetSizeMemStream( Strm: PStream; NewSize: DWORD );
956 function ReadMemStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
957 function WriteMemStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
958 procedure CloseMemStream( Strm: PStream );
959 procedure SetSizeFileStream( Strm: PStream; NewSize: DWORD );
961 function DummyReadWrite( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
962 procedure DummySetSize( Strm: PStream; Value: DWORD );
963 procedure DummyStreamProc(Strm: PStream);
966 //[NewFileStream DECLARATION]
967 function NewFileStream( const FileName: String; Options: DWORD ): PStream;
968 {* Creates file stream for read and write. Exact set of open attributes
969 should be passed through Options parameter (see FileCreate where those
970 flags are listed). }
972 function NewReadFileStream( const FileName: String ): PStream;
973 {* Creates file stream for read only. }
975 function NewWriteFileStream( const FileName: String ): PStream;
976 {* Creates file stream for write only. Truncating of file (if needed)
977 is provided automatically. }
979 function NewReadWriteFileStream( const FileName: String ): PStream;
980 {* Creates stream for read and write file. To truncate file, if it is
981 necessary, change Size property. }
983 //[NewMemoryStream DECLARATION]
984 function NewMemoryStream: PStream;
985 {* Creates memory stream (read and write). }
987 function NewExMemoryStream( ExistingMem: Pointer; Size: DWORD ): PStream;
988 {* Creates memory stream on base of existing memory. It is not possible
989 to write out of top bound given by Size (i.e. memory can not be resized,
990 or reallocated. When stream object is destroyed this memory is not freed. }
992 //[Stream2Stream DECLARATION]
993 function Stream2Stream( Dst, Src: PStream; Count: DWORD ): DWORD;
994 {* Copies Count (or less, if the rest of Src is not sufficiently long)
995 bytes from Src to Dst, but with optimizing in cases, when Src or/and
996 Dst are memory streams (intermediate buffer is not allocated). }
997 function Stream2StreamEx( Dst, Src: PStream; Count: DWORD ): DWORD;
998 {* Copies Count bytes from Src to Dst, but without any optimization.
999 Unlike Stream2Stream function, it can be applied to very large streams.
1000 See also Stream2StreamExBufSz. }
1001 function Stream2StreamExBufSz( Dst, Src: PStream; Count, BufSz: DWORD ): DWORD;
1002 {* Copies Count bytes from Src to Dst using buffer of given size, but without
1003 other optimizations.
1004 Unlike Stream2Stream function, it can be applied to very large streams }
1006 //[Resource2Stream DECLARATION]
1007 function Resource2Stream( DestStrm : PStream; Inst : HInst;
1008 ResName : PChar; ResType : PChar ): Integer;
1009 {* Loads given resource to DestStrm. Useful for non-standard
1010 resources to load it into memory (use memory stream for such
1011 purpose). Use one of following resource types to pass as ResType:
1012 |<pre>
1013 RT_ACCELERATOR Accelerator table
1014 RT_ANICURSOR Animated cursor
1015 RT_ANIICON Animated icon
1016 RT_BITMAP Bitmap resource
1017 RT_CURSOR Hardware-dependent cursor resource
1018 RT_DIALOG Dialog box
1019 RT_FONT Font resource
1020 RT_FONTDIR Font directory resource
1021 RT_GROUP_CURSOR Hardware-independent cursor resource
1022 RT_GROUP_ICON Hardware-independent icon resource
1023 RT_ICON Hardware-dependent icon resource
1024 RT_MENU Menu resource
1025 RT_MESSAGETABLE Message-table entry
1026 RT_RCDATA Application-defined resource (raw data)
1027 RT_STRING String-table entry
1028 RT_VERSION Version resource
1029 |</pre>
1030 |<br>For example:
1031 !var MemStrm: PStream;
1032 ! JpgObj: PJpeg;
1033 !......
1034 ! MemStrm := NewMemoryStream;
1035 ! JpgObj := NewJpeg;
1036 !......
1037 ! Resource2Stream( MemStrm, hInstance, 'MYJPEG', RT_RCDATA );
1038 ! MemStrm.Position := 0;
1039 ! JpgObj.LoadFromStream( MemStrm );
1040 ! MemStrm.Free;
1041 !......
1067 type
1068 //[TBits DEFINITION]
1069 {++}(*TBits = class;*){--}
1070 PBits = {-}^{+}TBits;
1071 TBits = object( TObj )
1072 {* Variable-length bits array object. Created using function NewBits. See also
1073 |<a href="kol_pas.htm#Small bit arrays (max 32 bits in array)">
1074 Small bit arrays (max 32 bits in array)
1075 |</a>. }
1076 protected
1077 fList: PList;
1078 fCount: Integer;
1079 function GetBit(Idx: Integer): Boolean;
1080 function GetCapacity: Integer;
1081 function GetSize: Integer;
1082 procedure SetBit(Idx: Integer; const Value: Boolean);
1083 procedure SetCapacity(const Value: Integer);
1084 public
1085 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
1086 {* }
1087 property Bits[ Idx: Integer ]: Boolean read GetBit write SetBit;
1088 {* }
1089 property Size: Integer read GetSize;
1090 {* Size in bytes of the array. To get know number of bits, use property Count. }
1091 property Count: Integer read fCount;
1092 {* Number of bits an the array. }
1093 property Capacity: Integer read GetCapacity write SetCapacity;
1094 {* Number of bytes allocated. Can be set before assigning bit values
1095 to improve performance (minimizing amount of memory allocation
1096 operations). }
1097 function Copy( From, BitsCount: Integer ): PBits;
1098 {* Use this property to get a sub-range of bits starting from given bit
1099 and of BitsCount bits count. }
1100 function IndexOf( Value: Boolean ): Integer;
1101 {* Returns index of first bit with given value (True or False). }
1102 function OpenBit: Integer;
1103 {* Returns index of the first bit not set to true. }
1104 procedure Clear;
1105 {* Clears bits array. Count, Size and Capacity become 0. }
1106 function LoadFromStream( strm: PStream ): Integer;
1107 {* Loads bits from the stream. Data should be stored in the stream
1108 earlier using SaveToStream method. While loading, previous bits
1109 data are discarded and replaced with new one totally. In part,
1110 Count of bits also is changed. Count of bytes read from the stream
1111 while loading data is returned. }
1112 function SaveToStream( strm: PStream ): Integer;
1113 {* Saves entire array of bits to the stream. First, Count of bits
1114 in the array is saved, then all bytes containing bits data. }
1115 function Range( Idx, N: Integer ): PBits;
1116 {* Creates and returns new TBits object instance containing N bits
1117 starting from index Idx. If you call this method, you are responsible
1118 for destroying returned object when it become not neccessary. }
1119 procedure AssignBits( ToIdx: Integer; FromBits: PBits; FromIdx, N: Integer );
1120 {* Assigns bits from another bits array object. N bits are assigned
1121 starting at index ToIdx. }
1122 end;
1123 //[END OF TBits DEFINITION]
1125 //[NewBits DECLARATION]
1126 function NewBits: PBits;
1127 {* Creates variable-length bits array object. }
1147 { -- string list objects -- }
1148 //[TStrList]
1150 type
1151 {++}(*TStrList = class;*){--}
1152 PStrList = {-}^{+}TStrList;
1153 { ---------------------------------------------------------------------
1155 TStrList - string list
1157 ---------------------------------------------------------------------- }
1158 //[TStrList DEFINITION]
1159 TStrList = object(TObj)
1160 {* Easy string list implementation (non-visual, just to store
1161 string data). It is well improved and has very high performance
1162 allowing to work fast with huge text files (more then megabyte
1163 of text data).
1165 Please note that #0 charaster if stored in string lines, will cut it
1166 preventing reading the rest of a line. Be careful, if your data
1167 contain such characters. }
1168 protected
1169 procedure Init; virtual;
1170 protected
1171 fList: PList;
1172 fCount: Integer;
1173 fCaseSensitiveSort: Boolean;
1174 fTextBuf: PChar;
1175 fTextSiz: DWORD;
1176 function GetPChars(Idx: Integer): PChar;
1177 //procedure AddTextBuf( Src: PChar; Len: DWORD );
1178 protected
1179 function Get(Idx: integer): string;
1180 function GetTextStr: string;
1181 procedure Put(Idx: integer; const Value: string);
1182 procedure SetTextStr(const Value: string);
1183 {++}(*public*){--}
1184 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
1185 protected
1186 // by Dod:
1187 procedure SetValue(const Name, Value: string);
1188 function GetValue(const Name: string): string;
1189 public
1190 // by Dod:
1191 function IndexOfName(Name: string): Integer;
1192 {* by Dod. Returns index of line starting like Name=... }
1193 property Values[const Name: string]: string read GetValue write SetValue;
1194 {* by Dod. Returns right side of a line starting like Name=... }
1195 public
1196 function Add(const S: string): integer;
1197 {* Adds a string to list. }
1198 procedure AddStrings(Strings: PStrList);
1199 {* Merges string list with given one. Very fast - more preferrable to
1200 use than any loop with calling Add method. }
1201 procedure Assign(Strings: PStrList);
1202 {* Fills string list with strings from other one. The same as AddStrings,
1203 but Clear is called first. }
1204 procedure Clear;
1205 {* Makes string list empty. }
1206 procedure Delete(Idx: integer);
1207 {* Deletes string with given index (it *must* exist). }
1208 function IndexOf(const S: string): integer;
1209 {* Returns index of first string, equal to given one. }
1210 function IndexOf_NoCase(const S: string): integer;
1211 {* Returns index of first string, equal to given one (while comparing it
1212 without case sensitivity). }
1213 function IndexOfStrL_NoCase( Str: PChar; L: Integer ): integer;
1214 {* Returns index of first string, equal to given one (while comparing it
1215 without case sensitivity). }
1216 function Find(const S: String; var Index: Integer): Boolean;
1217 {* Returns Index of the first string, equal or greater to given pattern, but
1218 works only for sorted TStrList object. Returns TRUE if exact string found,
1219 otherwise nearest (greater then a pattern) string index is returned,
1220 and the result is FALSE. }
1221 procedure Insert(Idx: integer; const S: string);
1222 {* Inserts string before one with given index. }
1223 function LoadFromFile(const FileName: string): Boolean;
1224 {* Loads string list from a file. (If file does not exist, nothing
1225 happens). Very fast even for huge text files. }
1226 procedure LoadFromStream(Stream: PStream; Append2List: boolean);
1227 {* Loads string list from a stream (from current position to the end of
1228 a stream). Very fast even for huge text. }
1229 procedure MergeFromFile(const FileName: string);
1230 {* Merges string list with strings in a file. Fast. }
1231 procedure Move(CurIndex, NewIndex: integer);
1232 {* Moves string to another location. }
1233 procedure SetText(const S: string; Append2List: boolean);
1234 {* Allows to set strings of string list from given string (in which
1235 strings are separated by $0D,$0A or $0D characters). Text must not
1236 contain #0 characters. Works very fast. This method is used in
1237 all others, working with text arrays (LoadFromFile, MergeFromFile,
1238 Assign, AddStrings). }
1239 procedure SetUnixText( const S: String; Append2List: Boolean );
1240 {* Allows to assign UNIX-style text (with #10 as string separator). }
1241 function SaveToFile(const FileName: string): Boolean;
1242 {* Stores string list to a file. }
1243 procedure SaveToStream(Stream: PStream);
1244 {* Saves string list to a stream (from current position). }
1245 function AppendToFile(const FileName: string): Boolean;
1246 {* Appends strings of string list to the end of a file. }
1247 property Count: integer read fCount;
1248 {* Number of strings in a string list. }
1249 property Items[Idx: integer]: string read Get write Put; default;
1250 {* Strings array items. If item does not exist, empty string is returned.
1251 But for assign to property, string with given index *must* exist. }
1252 property ItemPtrs[ Idx: Integer ]: PChar read GetPChars;
1253 {* Fast access to item strings as PChars. }
1254 function Last: String;
1255 {* Last item (or '', if string list is empty). }
1256 property Text: string read GetTextStr write SetTextStr;
1257 {* Content of string list as a single string (where strings are separated
1258 by characters $0D,$0A). }
1259 procedure Swap( Idx1, Idx2 : Integer );
1260 {* Swaps to strings with given indeces. }
1261 procedure Sort( CaseSensitive: Boolean );
1262 {* Call it to sort string list. }
1263 procedure AnsiSort( CaseSensitive: Boolean );
1264 {* Call it to sort ANSI string list. }
1266 // by Alexander Pravdin:
1267 protected
1268 fNameDelim: Char;
1269 function GetLineName( Idx: Integer ): string;
1270 procedure SetLineName( Idx: Integer; const NV: string );
1271 function GetLineValue(Idx: Integer): string;
1272 procedure SetLineValue(Idx: Integer; const Value: string);
1273 public
1274 property LineName[ Idx: Integer ]: string read GetLineName write SetLineName;
1275 property LineValue[ Idx: Integer ]: string read GetLineValue write SetLineValue;
1276 property NameDelimiter: Char read fNameDelim write fNameDelim;
1277 end;
1278 //[END OF TStrList DEFINITION]
1280 //[DefaultNameDelimiter]
1281 var DefaultNameDelimiter: Char = '=';
1283 //[NewStrList DECLARATION]
1284 function NewStrList: PStrList;
1285 {* Creates string list object. }
1287 function GetFileList(const dir: string): PStrList;
1288 {* By Alexander Shakhaylo. Returns list of file names of the given directory. }
1293 //[TStrListEx]
1294 type
1295 {++}(*TStrListEx = class;*){--}
1296 PStrListEx = {-}^{+}TStrListEx;
1298 //[TStrListEx DEFINITION]
1299 TStrListEx = object( TStrList )
1300 {* Extended string list object. Has additional capability to associate
1301 numbers or objects with string list items. }
1302 protected
1303 FObjects: PList;
1304 function GetObjects(Idx: Integer): DWORD;
1305 procedure SetObjects(Idx: Integer; const Value: DWORD);
1306 procedure Init; {-}virtual;{+}{++}(*override;*){--}
1307 procedure ProvideObjCapacity( NewCap: Integer );
1308 public
1309 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
1310 {* }
1311 property Objects[ Idx: Integer ]: DWORD read GetObjects write SetObjects;
1312 {* Objects are just 32-bit values. You can treat and use it as pointers to
1313 any other data in the memory. But it is your task to free allocated
1314 memory in such case therefore. }
1315 procedure AddStrings(Strings: PStrListEx);
1316 {* Merges string list with given one. Very fast - more preferrable to
1317 use than any loop with calling Add method. }
1318 procedure Assign(Strings: PStrListEx);
1319 {* Fills string list with strings from other one. The same as AddStrings,
1320 but Clear is called first. }
1321 procedure Clear;
1322 {* Makes string list empty. }
1323 procedure Delete(Idx: integer);
1324 {* Deletes string with given index (it *must* exist). }
1325 procedure Move(CurIndex, NewIndex: integer);
1326 {* Moves string to another location. }
1327 procedure Swap( Idx1, Idx2 : Integer );
1328 {* Swaps to strings with given indeces. }
1329 procedure Sort( CaseSensitive: Boolean );
1330 {* Call it to sort string list. }
1331 procedure AnsiSort( CaseSensitive: Boolean );
1332 {* Call it to sort ANSI string list. }
1333 function LastObj: DWORD;
1334 {* Object assotiated with the last string. }
1335 function AddObject( const S: String; Obj: DWORD ): Integer;
1336 {* Adds a string and associates given number with it. Index of the item added
1337 is returned. }
1338 procedure InsertObject( Before: Integer; const S: String; Obj: DWORD );
1339 {* Inserts a string together with object associated. }
1340 function IndexOfObj( Obj: Pointer ): Integer;
1341 {* Returns an index of a string associated with the object passed as a
1342 parameter. If there are no such strings, -1 is returned. }
1343 end;
1344 //[END OF TStrListEx DEFINITION]
1346 //[NewStrListEx DECLARATION]
1347 function NewStrListEx: PStrListEx;
1348 {* Creates extended string list object. }
1354 //[TWStrList]
1357 {$IFNDEF _D2} //------------------ WideString is not supported in D2 -----------
1359 type
1360 PWStrList = ^TWstrList;
1361 {* }
1362 //[TWstrList DEFINITION]
1363 TWStrList = object( TObj )
1364 {* String list to store Unicode (null-terminated) strings. }
1365 protected
1366 function GetCount: Integer;
1367 function GetItems(Idx: Integer): WideString;
1368 procedure SetItems(Idx: Integer; const Value: WideString);
1369 function GetPtrs(Idx: Integer): PWideChar;
1370 function GetText: WideString;
1371 protected
1372 fList: PList;
1373 fText: PWideChar;
1374 fTextBufSz: Integer;
1375 fTmp1, fTmp2: WideString;
1376 procedure Init; virtual;
1377 public
1378 procedure SetText(const Value: WideString);
1379 {* See also TStrList.SetText }
1380 destructor Destroy; virtual;
1381 {* }
1382 procedure Clear;
1383 {* See also TStrList.Clear }
1384 property Items[ Idx: Integer ]: WideString read GetItems write SetItems;
1385 {* See also TStrList.Items }
1386 property ItemPtrs[ Idx: Integer ]: PWideChar read GetPtrs;
1387 {* See also TStrList.ItemPtrs }
1388 property Count: Integer read GetCount;
1389 {* See also TStrList.Count }
1390 function Add( const W: WideString ): Integer;
1391 {* See also TStrList.Add }
1392 procedure Insert( Idx: Integer; const W: WideString );
1393 {* See also TStrList.Insert }
1394 procedure Delete( Idx: Integer );
1395 {* See also TStrList.Delete }
1396 property Text: WideString read GetText write SetText;
1397 {* See also TStrList.Text }
1398 procedure AddWStrings( WL: PWStrList );
1399 {* See also TStrList.AddStrings }
1400 procedure Assign( WL: PWStrList );
1401 {* See also TStrList.Assign }
1402 function LoadFromFile( const Filename: String ): Boolean;
1403 {* See also TStrList.LoadFromFile }
1404 procedure LoadFromStream( Strm: PStream );
1405 {* See also TStrList.LoadFromStream }
1406 function MergeFromFile( const Filename: String ): Boolean;
1407 {* See also TStrList.MergeFromFile }
1408 procedure MergeFromStream( Strm: PStream );
1409 {* See also TStrList.MergeFromStream }
1410 function SaveToFile( const Filename: String ): Boolean;
1411 {* See also TStrList.SaveToFile }
1412 procedure SaveToStream( Strm: PStream );
1413 {* See also TStrList.SaveToStream }
1414 function AppendToFile( const Filename: String ): Boolean;
1415 {* See also TStrList.AppendToFile }
1416 procedure Swap( Idx1, Idx2: Integer );
1417 {* See also TStrList.Swap }
1418 procedure Sort( CaseSensitive: Boolean );
1419 {* See also TStrList.Sort }
1420 procedure Move( IdxOld, IdxNew: Integer );
1421 {* See also TStrList.Move }
1422 end;
1423 //[END OF TWStrList DEFINITION]
1425 //[TWStrListEx]
1426 PWStrListEx = ^TWStrListEx;
1428 //[TWStrListEx DEFINITION]
1429 TWStrListEx = object( TWStrList )
1430 {* Extended Unicode string list (with Objects). }
1431 protected
1432 function GetObjects(Idx: Integer): DWORD;
1433 procedure SetObjects(Idx: Integer; const Value: DWORD);
1434 procedure ProvideObjectsCapacity( NewCap: Integer );
1435 protected
1436 fObjects: PList;
1437 procedure Init; virtual;
1438 public
1439 destructor Destroy; virtual;
1440 {* }
1441 property Objects[ Idx: Integer ]: DWORD read GetObjects write SetObjects;
1442 {* }
1443 procedure AddWStrings( WL: PWStrListEx );
1444 {* }
1445 procedure Assign( WL: PWStrListEx );
1446 {* }
1447 procedure Clear;
1448 {* }
1449 procedure Delete( Idx: Integer );
1450 {* }
1451 procedure Move( IdxOld, IdxNew: Integer );
1452 {* }
1453 function AddObject( const S: WideString; Obj: DWORD ): Integer;
1454 {* Adds a string and associates given number with it. Index of the item added
1455 is returned. }
1456 procedure InsertObject( Before: Integer; const S: WideString; Obj: DWORD );
1457 {* Inserts a string together with object associated. }
1458 function IndexOfObj( Obj: Pointer ): Integer;
1459 {* Returns an index of a string associated with the object passed as a
1460 parameter. If there are no such strings, -1 is returned. }
1461 end;
1462 //[END OF TWStrListEx DEFINITION]
1464 //[NewWStrList DECLARATION]
1465 function NewWStrList: PWStrList;
1466 {* Creates new TWStrList object and returns a pointer to it. }
1468 //[NewWStrListEx DECLARATION]
1469 function NewWStrListEx: PWStrListEx;
1470 {* Creates new TWStrListEx objects and returns a pointer to it. }
1472 {$ENDIF}
1490 ////////////////////////////////////////////////////////////////////////////////
1491 // GRAPHIC OBJECTS //
1492 ////////////////////////////////////////////////////////////////////////////////
1493 //[GRAPHIC OBJECTS]
1495 It is very important, that the most of code, implementing graphic objets
1496 from this section, is included into executable ONLY if really accessed in your
1497 project directly (e.g., if Font or Brush properies of a control are accessed
1498 or changed).
1500 type
1501 TColor = Integer;
1503 const
1504 //[COLOR CONSTANTS]
1505 clScrollBar = TColor(COLOR_SCROLLBAR or $80000000);
1506 clBackground = TColor(COLOR_BACKGROUND or $80000000);
1507 clActiveCaption = TColor(COLOR_ACTIVECAPTION or $80000000);
1508 clInactiveCaption = TColor(COLOR_INACTIVECAPTION or $80000000);
1509 clMenu = TColor(COLOR_MENU or $80000000);
1510 clWindow = TColor(COLOR_WINDOW or $80000000);
1511 clWindowFrame = TColor(COLOR_WINDOWFRAME or $80000000);
1512 clMenuText = TColor(COLOR_MENUTEXT or $80000000);
1513 clWindowText = TColor(COLOR_WINDOWTEXT or $80000000);
1514 clCaptionText = TColor(COLOR_CAPTIONTEXT or $80000000);
1515 clActiveBorder = TColor(COLOR_ACTIVEBORDER or $80000000);
1516 clInactiveBorder = TColor(COLOR_INACTIVEBORDER or $80000000);
1517 clAppWorkSpace = TColor(COLOR_APPWORKSPACE or $80000000);
1518 clHighlight = TColor(COLOR_HIGHLIGHT or $80000000);
1519 clHighlightText = TColor(COLOR_HIGHLIGHTTEXT or $80000000);
1520 clBtnFace = TColor(COLOR_BTNFACE or $80000000);
1521 clBtnShadow = TColor(COLOR_BTNSHADOW or $80000000);
1522 clGrayText = TColor(COLOR_GRAYTEXT or $80000000);
1523 clBtnText = TColor(COLOR_BTNTEXT or $80000000);
1524 clInactiveCaptionText = TColor(COLOR_INACTIVECAPTIONTEXT or $80000000);
1525 clBtnHighlight = TColor(COLOR_BTNHIGHLIGHT or $80000000);
1526 cl3DDkShadow = TColor(COLOR_3DDKSHADOW or $80000000);
1527 cl3DLight = TColor(COLOR_3DLIGHT or $80000000);
1528 clInfoText = TColor(COLOR_INFOTEXT or $80000000);
1529 clInfoBk = TColor(COLOR_INFOBK or $80000000);
1531 clBlack = TColor($000000);
1532 clMaroon = TColor($000080);
1533 clGreen = TColor($008000);
1534 clOlive = TColor($008080);
1535 clNavy = TColor($800000);
1536 clPurple = TColor($800080);
1537 clTeal = TColor($808000);
1538 clGray = TColor($808080);
1539 clSilver = TColor($C0C0C0);
1540 clRed = TColor($0000FF);
1541 clLime = TColor($00FF00);
1542 clYellow = TColor($00FFFF);
1543 clBlue = TColor($FF0000);
1544 clFuchsia = TColor($FF00FF);
1545 clAqua = TColor($FFFF00);
1546 clLtGray = TColor($C0C0C0);
1547 clDkGray = TColor($808080);
1548 clWhite = TColor($FFFFFF);
1549 clNone = TColor($1FFFFFFF);
1550 clDefault = TColor($20000000);
1552 clMoneyGreen = TColor($C0DCC0);
1553 clSkyBlue = TColor($F0CAA6);
1554 clCream = TColor($F0FBFF);
1555 clMedGray = TColor($A4A0A0);
1556 //[END OF COLOR CONSTANTS]
1558 const
1559 //[TGraphicTool FIELD OFFSET CONSTANTS]
1560 go_Color = 0;
1561 go_FontHeight = 4;
1562 go_FontWidth = 8;
1563 go_FontEscapement = 12;
1564 go_FontOrientation = 16;
1565 go_FontWeight = 20;
1566 go_FontItalic = 24;
1567 go_FontUnderline = 25;
1568 go_FontStrikeOut = 26;
1569 go_FontCharSet = 27;
1570 go_FontOutPrecision = 28;
1571 go_FontClipPrecision = 29;
1572 go_FontQuality = 30;
1573 go_FontPitch = 31;
1574 go_FontName = 32;
1575 go_BrushBitmap = 4;
1576 go_BrushStyle = 8;
1577 go_BrushLineColor = 9;
1578 go_PenBrushBitmap = 4;
1579 go_PenBrushStyle = 8;
1580 go_PenStyle = 9;
1581 go_PenWidth = 10;
1582 go_PenMode = 14;
1583 go_PenGeometric = 15;
1584 go_PenEndCap = 16;
1585 go_PenJoin = 17;
1586 //[END OF TGraphicTool FIELD OFFSET CONSTANTS]
1588 //[TGraphicTool]
1589 type
1590 TGraphicToolType = ( gttBrush, gttFont, gttPen );
1591 {* Graphic object types, mainly for internal use. }
1593 {++}(*TGraphicTool = class;*){--}
1594 PGraphicTool = {-}^{+}TGraphicTool;
1595 {* }
1596 TOnGraphicChange = procedure ( Sender: PGraphicTool ) of object;
1597 {* An event mainly for internal use. }
1599 TBrushStyle = (bsSolid, bsClear, bsHorizontal, bsVertical,
1600 bsFDiagonal, bsBDiagonal, bsCross, bsDiagCross);
1601 {* Available brush styles. }
1603 TFontStyles = (fsBold, fsItalic, fsUnderline, fsStrikeOut);
1604 {* Available font styles. }
1605 TFontStyle = set of TFontStyles;
1606 {* Font style is representing as a set of XFontStyles. }
1607 TFontPitch = (fpDefault, fpFixed, fpVariable);
1608 {* Availabe font pitch values. }
1609 TFontName = type string;
1610 {* Font name is represented as a string. }
1611 TFontCharset = 0..255;
1612 {* Font charset is represented by number from 0 to 255. }
1613 TFontQuality = (fqDefault, fqDraft, fqProof, fqNonAntialiased, fqAntialiased);
1614 {* Font quality. }
1616 TPenStyle = (psSolid, psDash, psDot, psDashDot, psDashDotDot, psClear,
1617 psInsideFrame);
1618 {* Available pen styles. For more info see Delphi or Win32 help files. }
1619 TPenMode = (pmBlack, pmNotMerge, pmMaskNotPen, pmNotCopy, pmMaskPenNot,
1620 pmNot, pmXor, pmNotMask, pmMask, pmNotXor, pmNop, pmMergePenNot,
1621 pmCopy, pmMergeNotPen, pmMerge, pmWhite);
1622 {* Available pen modes. For more info see Delphi or Win32 help files. }
1623 TPenEndCap = (pecRound, pecSquare, pecFlat);
1624 {* Avalable (for geometric pen) end cap styles. }
1625 TPenJoin = (pjRound, pjBevel, pjMiter);
1626 {* Available (for geometric pen) join styles. }
1628 //[TGdiFont]
1629 TGDIFont = packed record
1630 Height: Integer;
1631 Width: Integer;
1632 Escapement: Integer;
1633 Orientation: Integer;
1634 Weight: Integer;
1635 Italic: Boolean;
1636 Underline: Boolean;
1637 StrikeOut: Boolean;
1638 CharSet: TFontCharset;
1639 OutPrecision: Byte;
1640 ClipPrecision: Byte;
1641 Quality: TFontQuality;
1642 Pitch: TFontPitch;
1643 Name: array[0..LF_FACESIZE - 1] of Char;
1644 end;
1646 //[TGDIBrush]
1647 TGDIBrush = packed record
1648 Bitmap: HBitmap;
1649 Style: TBrushStyle;
1650 LineColor: TColor;
1651 end;
1653 //[TGDIPen]
1654 TGDIPen = packed record
1655 BrushBitmap: HBitmap;
1656 BrushStyle: TBrushStyle;
1657 Style: TPenStyle;
1658 Width: Integer;
1659 Mode: TPenMode;
1660 Geometric: Boolean;
1661 EndCap: TPenEndCap;
1662 Join: TPenJoin;
1663 end;
1665 //[TGDIToolData]
1666 TGDIToolData = packed record
1667 Color: TColor;
1668 case Integer of
1669 1: (Font: TGDIFont);
1670 2: (Pen: TGDIPen);
1671 3: (Brush: TGDIBrush);
1672 end;
1674 //[TNewGraphicTool]
1675 TNewGraphicTool = function: PGraphicTool;
1677 { ---------------------------------------------------------------------
1679 TGraphicTool - object to implement GDI-tools (brush, pen, font)
1681 ---------------------------------------------------------------------- }
1682 //[TGraphicTool DEFINITION]
1683 TGraphicTool = object( TObj )
1684 {* Incapsulates all GDI objects: Pen, Brush and Font. }
1685 protected
1686 fType: TGraphicToolType;
1687 fHandle: THandle;
1688 fParentGDITool: PGraphicTool;
1689 fOnChange: TOnGraphicChange;
1690 fColorRGB: TColor;
1691 fData: TGDIToolData;
1693 fNewProc: TNewGraphicTool;
1694 fMakeHandleProc: function( Self_: PGraphicTool ): THandle;
1696 procedure SetInt( const Index: Integer; Value: Integer );
1697 {$IFDEF F_P}
1698 function GetInt( const Index: Integer ): Integer;
1699 {$ENDIF}
1700 procedure SetColor( Value: TColor );
1701 procedure SetBrushBitmap(const Value: HBitmap);
1702 procedure SetBrushStyle(const Value: TBrushStyle);
1703 procedure SetFontCharset(const Value: TFontCharset);
1704 procedure SetFontQuality(const Value: TFontQuality);
1705 function GetFontName: String;
1706 procedure SetFontName(const Value: String);
1707 procedure SetFontOrientation(Value: Integer);
1708 procedure SetFontPitch(const Value: TFontPitch);
1709 function GetFontStyle: TFontStyle;
1710 procedure SetFontStyle(const Value: TFontStyle);
1711 procedure SetPenMode(const Value: TPenMode);
1712 procedure SetPenStyle(const Value: TPenStyle);
1713 procedure SetGeometricPen(const Value: Boolean);
1714 procedure SetPenEndCap(const Value: TPenEndCap);
1715 procedure SetPenJoin(const Value: TPenJoin);
1716 procedure SetFontWeight(const Value: Integer);
1717 procedure SetLogFontStruct(const Value: TLogFont);
1718 function GetLogFontStruct: TLogFont;
1719 protected
1720 procedure Changed;
1721 {* }
1722 function GetHandle: THandle;
1723 {* }
1724 public
1725 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
1726 {* }
1727 property Handle: THandle read GetHandle;
1728 {* Every time, when accessed, real GDI object is created (if it is
1729 not yet created). So, to prevent creating of the handle, use
1730 HandleAllocated instead of comparing Handle with value 0. }
1731 function HandleAllocated: Boolean;
1732 {* Returns True, if handle is allocated (i.e., if real GDI
1733 objet is created. }
1734 property OnChange: TOnGraphicChange read fOnChange write fOnChange;
1735 {* Called, when object is changed. }
1736 function ReleaseHandle: Integer;
1737 {* Returns Handle value (if allocated), releasing it from the
1738 object (so, it is no more knows about this handle and its
1739 HandleAllocated function returns False. }
1740 property Color: TColor {index go_Color} read fData.Color write SetColor;
1741 {* Color is the most common property for all Pen, Brush and
1742 Font objects, so it is placed in its common for all of them. }
1743 function Assign( Value: PGraphicTool ): PGraphicTool;
1744 {* Assigns properties of the same (only) type graphic object,
1745 excluding Handle. If assigning is really leading to change
1746 object, procedure Changed is called. }
1747 procedure AssignHandle( NewHandle: Integer );
1748 {* Assigns value to Handle property. }
1750 property BrushBitmap: HBitmap read fData.Brush.Bitmap write SetBrushBitmap;
1751 {* Brush bitmap. For more info about using brush bitmap,
1752 see Delphi or Win32 help files. }
1753 property BrushStyle: TBrushStyle read fData.Brush.Style write SetBrushStyle;
1754 {* Brush style. }
1755 property BrushLineColor: TColor index go_BrushLineColor
1756 {$IFDEF F_P}
1757 read GetInt
1758 {$ELSE DELPHI}
1759 read fData.Brush.LineColor
1760 {$ENDIF F_P/DELPHI}
1761 write SetInt;
1762 {* Brush line color, used to represent lines in hatched brush. Default value is clBlack. }
1764 property FontHeight: Integer index go_FontHeight
1765 {$IFDEF F_P}
1766 read GetInt
1767 {$ELSE DELPHI}
1768 read fData.Font.Height
1769 {$ENDIF F_P/DELPHI}
1770 write SetInt;
1771 {* Font height. Value 0 (default) seys to use system default value,
1772 negative values are to represent font height in "points", positive
1773 - in pixels. In XCL usually positive values (if not 0) are used to
1774 make appearance independent from different local settings. }
1775 property FontWidth: Integer index go_FontWidth
1776 {$IFDEF F_P}
1777 read GetInt
1778 {$ELSE DELPHI}
1779 read fData.Font.Width
1780 {$ENDIF F_P/DELPHI}
1781 write SetInt;
1782 {* Font width in logical units. If FontWidth = 0, then as it is said
1783 in Win32.hlp, "the aspect ratio of the device is matched against the
1784 digitization aspect ratio of the available fonts to find the closest match,
1785 determined by the absolute value of the difference." }
1786 property FontPitch: TFontPitch read fData.Font.Pitch write SetFontPitch;
1787 {* Font pitch. Change it very rare. }
1788 property FontStyle: TFontStyle read GetFontStyle write SetFontStyle;
1789 {* Very useful property to control text appearance. }
1790 property FontCharset: TFontCharset read fData.Font.Charset write SetFontCharset;
1791 {* Do not change it if You do not know what You do. }
1792 property FontQuality: TFontQuality read fData.Font.Quality write SetFontQuality;
1793 {* Font quality. }
1794 property FontOrientation: Integer read fData.Font.Orientation write SetFontOrientation;
1795 {* It is possible to rotate text in XCL just by changing this
1796 property of a font (tenths of degree, i.e. value 900 represents
1797 90 degree - text written from bottom to top). }
1798 property FontWeight: Integer read fData.Font.Weight write SetFontWeight;
1799 {* Additional font weight for bold fonts (must be 0..1000). When set to
1800 value <> 0, fsBold is added to FontStyle. And otherwise, when set to 0,
1801 fsBold is removed from FontStyle. Value 700 corresponds to Bold,
1802 400 to Normal. }
1803 property FontName: String read GetFontName write SetFontName;
1804 {* Font face name. }
1805 function IsFontTrueType: Boolean;
1806 {* Returns True, if font is True Type. Requires of creating of a Handle,
1807 if it is not yet created. }
1809 property PenWidth: Integer index go_PenWidth
1810 {$IFDEF F_P}
1811 read GetInt
1812 {$ELSE DELPHI}
1813 read fData.Pen.Width
1814 {$ENDIF F_P/DELPHI}
1815 write SetInt;
1816 {* Value 0 means default pen width. }
1817 property PenStyle: TPenStyle read fData.Pen.Style write SetPenStyle;
1818 {* Pen style. }
1819 property PenMode: TPenMode read fData.Pen.Mode write SetPenMode;
1820 {* Pen mode. }
1822 property GeometricPen: Boolean read fData.Pen.Geometric write SetGeometricPen;
1823 {* True if Pen is geometric. Note, that under Win95/98 only pen styles
1824 psSolid, psNull, psInsideFrame are supported by OS. }
1825 property PenBrushStyle: TBrushStyle read fData.Pen.BrushStyle write SetBrushStyle;
1826 {* Brush style for hatched geometric pen. }
1827 property PenBrushBitmap: HBitmap read fData.Pen.BrushBitmap write SetBrushBitmap;
1828 {* Brush bitmap for geometric pen (if assigned Pen is functioning as
1829 its style = BS_PATTERN, regadless of PenBrushStyle value). }
1830 property PenEndCap: TPenEndCap read fData.Pen.EndCap write SetPenEndCap;
1831 {* Pen end cap mode - for GeometricPen only. }
1832 property PenJoin: TPenJoin read fData.Pen.Join write SetPenJoin;
1833 {* Pen join mode - for GeometricPen only. }
1834 property LogFontStruct: TLogFont read GetLogFontStruct write SetLogFontStruct;
1835 {* by Alex Pravdin: a property to change all font structure items at once. }
1836 end;
1837 //[END OF TGraphicTool DEFINITION]
1839 //[Color2XXX FUNCTIONS]
1840 function Color2RGB( Color: TColor ): TColor;
1841 {* Function to get RGB color from system color. Parameter can be also RGB
1842 color, in that case result is just equal to a parameter. }
1843 function ColorsMix( Color1, Color2: TColor ): TColor;
1844 {* Returns color, which RGB components are build as an (approximate)
1845 arithmetic mean of correspondent RGB components of both source
1846 colors (these both are first converted from system to RGB, and
1847 result is always RGB color). Please note: this function is fast,
1848 but can be not too exact. }
1849 function Color2RGBQuad( Color: TColor ): TRGBQuad;
1850 {* Converts color to RGB, used to represent RGB values in palette entries
1851 (actually swaps R and B bytes). }
1852 function Color2Color16( Color: TColor ): WORD;
1853 {* Converts Color to RGB, packed to word (as it is used in format pf16bit). }
1855 //[DefFont VARIABLE]
1856 var // New TFont instances are intialized with the values in this structure:
1857 DefFont: TGDIFont = (
1858 Height: 0;
1859 Width: 0;
1860 Escapement: 0;
1861 Orientation: 0;
1862 Weight: 0;
1863 Italic: FALSE;
1864 Underline: FALSE;
1865 StrikeOut: FALSE;
1866 CharSet: 1;
1867 OutPrecision: 0;
1868 ClipPrecision: 0;
1869 Quality: fqDefault;
1870 Pitch: fpDefault;
1871 Name: 'MS Sans Serif';
1873 DefFontColor: TColor = clWindowText;
1874 {* Default font color. }
1876 //[GlobalGraphics_UseFontOrient]
1877 GlobalGraphics_UseFontOrient: Boolean;
1878 {* Global flag. If stays False (default), Orientation property of Font
1879 objects is ignored. This flag is set to True automatically in
1880 RotateFonts add-on. }
1882 { -- Constructors for different GDI tools -- }
1884 //[New FUNCTIONS FOR TGraphicTool]
1885 function NewFont: PGraphicTool;
1886 {* Creates and returns font graphic tool object. }
1887 function NewBrush: PGraphicTool;
1888 {* Creates and returns new brush object. }
1889 function NewPen: PGraphicTool;
1890 {* Creates and returns new pen object. }
1905 { -- TCanvas object -- }
1906 //[TCanvas]
1907 const
1908 HandleValid = 1;
1909 PenValid = 2;
1910 BrushValid = 4;
1911 FontValid = 8;
1912 ChangingCanvas = 16;
1914 type
1915 TFillStyle = (fsSurface, fsBorder);
1916 {* Available filling styles. For more info see Win32 or Delphi help files. }
1917 TFillMode = (fmAlternate, fmWinding);
1918 {* Available filling modes. For more info see Win32 or Delphi help files. }
1919 TCopyMode = Integer;
1920 {* Available copying modes are following:
1921 | cmBlackness<br>
1922 | cmDstInvert<br>
1923 | cmMergeCopy<br>
1924 | cmMergePaint<br>
1925 | cmNotSrcCopy<br>
1926 | cmNotSrcErase<br>
1927 | cmPatCopy<br>
1928 | cmPatInvert<br>
1929 | cmPatPaint<br>
1930 | cmSrcAnd<br>
1931 | cmSrcCopy<br>
1932 | cmSrcErase<br>
1933 | cmSrcInvert<br>
1934 | cmSrcPaint<br>
1935 | cmWhiteness<br>&nbsp;&nbsp;&nbsp;
1936 Also it is possible to use any other available ROP2 modes. For more info,
1937 see Win32 help files. }
1939 const
1940 cmBlackness = BLACKNESS;
1941 cmDstInvert = DSTINVERT;
1942 cmMergeCopy = MERGECOPY;
1943 cmMergePaint = MERGEPAINT;
1944 cmNotSrcCopy = NOTSRCCOPY;
1945 cmNotSrcErase = NOTSRCERASE;
1946 cmPatCopy = PATCOPY;
1947 cmPatInvert = PATINVERT;
1948 cmPatPaint = PATPAINT;
1949 cmSrcAnd = SRCAND;
1950 cmSrcCopy = SRCCOPY;
1951 cmSrcErase = SRCERASE;
1952 cmSrcInvert = SRCINVERT;
1953 cmSrcPaint = SRCPAINT;
1954 cmWhiteness = WHITENESS;
1956 type
1957 {++}(*TCanvas = class;*){--}
1958 PCanvas = {-}^{+}TCanvas;
1959 {* }
1960 TOnGetHandle = function( Canvas: PCanvas ): HDC of object;
1961 {* For internal use mainly. }
1962 TOnTextArea = procedure( Sender: PCanvas; var Size : TSize; var P0 : TPoint );
1963 {* Event to calculate actual area, occupying by a text. It is used
1964 to optionally extend calculating of TextArea taking into considaration
1965 font Orientation property. }
1967 { ---------------------------------------------------------------------
1969 TCanvas - high-level drawing helper object
1971 ----------------------------------------------------------------------- }
1972 //[TCanvas DEFINITION]
1973 TCanvas = object( TObj )
1974 {* Very similar to VCL's TCanvas object. But with some changes, specific
1975 for KOL: there is no necessary to use canvases in all applications.
1976 And graphic tools objects are not created with canvas, but only
1977 if really accessed in program. (Actually, even if paint box used,
1978 only programmer decides, if to implement painting using Canvas or
1979 to call low level API drawing functions working directly with DC).
1980 Therefore TCanvas has some powerful extensions: rotated text support,
1981 geometric pen support - just by changing correspondent properties
1982 of certain graphic tool objects (Font.FontOrientation, Pen.GeometricPen).
1983 See also additional Font properties (Font.FontWeight, Font.FontQuality,
1984 etc. }
1985 protected
1986 fOwnerControl: Pointer; //PControl;
1987 fHandle : HDC;
1988 fPenPos : TPoint;
1989 fBrush, fFont, fPen : PGraphicTool; // order is important for ASM version
1990 fState : Byte;
1991 fCopyMode : TCopyMode;
1992 fOnChange: TOnEvent;
1993 fOnGetHandle: TOnGetHandle;
1994 procedure SetHandle( Value : HDC );
1995 procedure SetPenPos( const Value : TPoint );
1996 procedure CreatePen;
1997 procedure CreateBrush;
1998 procedure CreateFont;
1999 procedure ObjectChanged( Sender : PGraphicTool );
2000 procedure Changing;
2001 function GetBrush: PGraphicTool;
2002 function GetFont: PGraphicTool;
2003 function GetPen: PGraphicTool;
2004 function GetHandle: HDC;
2005 procedure AssignChangeEvents;
2006 function GetPixels(X, Y: Integer): TColor;
2007 procedure SetPixels(X, Y: Integer; const Value: TColor);
2008 protected
2009 fIsPaintDC : Boolean;
2010 {* TRUE, if DC obtained during current WM_PAINT (or WM_ERASEBKGND?)
2011 processing for a control. This affects a way how Handle is released. }
2012 {++}(*public*){--}
2013 destructor Destroy;{-}virtual;{+}{++}(*override;*){--}
2014 {* }
2015 {++}(*protected*){--}
2016 property OnGetHandle: TOnGetHandle read fOnGetHandle write fOnGetHandle;
2017 {* For internal use only. }
2018 public
2019 property Handle : HDC read GetHandle write SetHandle;
2020 {* GDI device context object handle. Never created by
2021 Canvas itself (to use Canvas with memory bitmaps,
2022 always create DC by yourself and assign it to the
2023 Handle property of Canvas object, or use property
2024 Canvas of a bitmap). }
2025 property PenPos : TPoint read FPenPos write SetPenPos;
2026 {* Position of a pen. }
2027 property Pen : PGraphicTool read GetPen;
2028 {* Pen of Canvas object. Do not change its Pen.OnChange event value. }
2029 property Brush : PGraphicTool read GetBrush;
2030 {* Brush of Canvas object. Do not change its Brush.OnChange event value. }
2031 property Font : PGraphicTool read GetFont;
2032 {* Font of Canvas object. Do not change its Font.OnChange event value. }
2033 procedure Arc(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
2034 {* Draws arc. For more info, see Delphi TCanvas help. }
2035 procedure Chord(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
2036 {* Draws chord. For more info, see Delphi TCanvas help. }
2037 procedure DrawFocusRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
2038 {* Draws rectangle to represent focused visual object.
2039 For more info, see Delphi TCanvas help. }
2040 procedure Ellipse(X1, Y1, X2, Y2: Integer);
2041 {* Draws an ellipse. For more info, see Delphi TCanvas help. }
2042 procedure FillRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
2043 {* Fills rectangle. For more info, see Delphi TCanvas help. }
2044 procedure FillRgn( const Rgn : HRgn );
2045 {* Fills region. For more info, see Delphi TCanvas help. }
2046 procedure FloodFill(X, Y: Integer; Color: TColor; FillStyle: TFillStyle);
2047 {* Fills a figure with givien color, floodfilling its surface.
2048 For more info, see Delphi TCanvas help. }
2049 procedure FrameRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
2050 {* Draws a rectangle. For more info, see Delphi TCanvas help. }
2051 procedure MoveTo( X, Y : Integer );
2052 {* Moves current PenPos to a new position.
2053 For more info, see Delphi TCanvas help. }
2054 procedure LineTo( X, Y : Integer );
2055 {* Draws a line from current PenPos up to new position.
2056 For more info, see Delphi TCanvas help. }
2057 procedure Pie(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
2058 {* Draws a pie. For more info, see Delphi TCanvas help. }
2059 procedure Polygon(const Points: array of TPoint);
2060 {* Draws a polygon. For more info, see Delphi TCanvas help. }
2061 procedure Polyline(const Points: array of TPoint);
2062 {* Draws a bound for polygon. For more info, see Delphi TCanvas help. }
2063 procedure Rectangle(X1, Y1, X2, Y2: Integer);
2064 {* Draws a rectangle using current Pen and/or Brush.
2065 For more info, see Delphi TCanvas help. }
2066 procedure RoundRect(X1, Y1, X2, Y2, X3, Y3: Integer);
2067 {* Draws a rounded rectangle. For more info, see Delphi TCanvas help. }
2068 procedure TextOut(X, Y: Integer; const Text: String); stdcall;
2069 {* Draws a text. For more info, see Delphi TCanvas help. }
2070 procedure ExtTextOut( X, Y: Integer; Options: DWORD; const Rect: TRect; const Text: String;
2071 const Spacing: array of Integer );
2072 {* }
2073 procedure DrawText(Text:String; var Rect:TRect; Flags:DWord);
2074 {* }
2075 procedure TextRect(const Rect: TRect; X, Y: Integer; const Text: string);
2076 {* Draws a text, clipping output into given rectangle.
2077 For more info, see Delphi TCanvas help. }
2078 function TextExtent(const Text: string): TSize;
2079 {* Calculates size of a Text, using current Font settings.
2080 Does not need in Handle for Canvas object (if it is not
2081 yet allocated, temporary device context is created and used. }
2082 procedure TextArea( const Text : String; var Sz : TSize; var P0 : TPoint );
2083 {* Calculates size and starting point to output Text,
2084 taking into considaration all Font attributes, including
2085 Orientation (only if GlobalGraphics_UseFontOrient flag
2086 is set to True, i.e. if rotated fonts are used).
2087 Like for TextExtent, does not need in Handle (and if this
2088 last is not yet allocated/assigned, temporary device context
2089 is created and used). }
2090 function TextWidth(const Text: string): Integer;
2091 {* Calculates text width (using TextArea). }
2092 function TextHeight(const Text: string): Integer;
2093 {* Calculates text height (using TextArea). }
2094 function ClipRect: TRect;
2095 {* returns ClipBox. by Dmitry Zharov. }
2097 {$IFNDEF _FPC}
2098 {$IFNDEF _D2} //------- WideString not supported in D2
2099 procedure WTextOut(X, Y: Integer; const WText: WideString); stdcall;
2100 {* Draws a Unicode text. }
2101 procedure WExtTextOut( X, Y: Integer; Options: DWORD; const Rect: TRect;
2102 const WText: WideString; const Spacing: array of Integer );
2103 {* }
2104 procedure WDrawText(WText: WideString; var Rect:TRect; Flags:DWord);
2105 {* }
2106 procedure WTextRect(const Rect: TRect; X, Y: Integer;
2107 const WText: WideString);
2108 {* Draws a Unicode text, clipping output into given rectangle. }
2109 function WTextExtent( const WText: WideString ): TSize;
2110 {* Calculates Unicode text width and height. }
2111 function WTextWidth( const WText: WideString ): Integer;
2112 {* Calculates Unicode text width. }
2113 function WTextHeight( const WText: WideString ): Integer;
2114 {* Calculates Unicode text height. }
2115 {$ENDIF _D2}
2116 {$ENDIF _FPC}
2118 property ModeCopy : TCopyMode read fCopyMode write fCopyMode;
2119 {* Current copy mode. Is used in CopyRect method. }
2120 procedure CopyRect( const DstRect : TRect; SrcCanvas : PCanvas; const SrcRect : TRect );
2121 {* Copyes a rectangle from source to destination, using StretchBlt. }
2122 property OnChange: TOnEvent read fOnChange write fOnChange;
2123 {* }
2124 function Assign( SrcCanvas : PCanvas ) : Boolean;
2125 {* }
2126 function RequiredState( ReqState : DWORD ): Integer; stdcall;// public now
2127 {* It is possible to call this method before using Handle property
2128 to pass it into API calls - to provide valid combinations of
2129 pen, brush and font, selected into device context. This method
2130 can not provide valid Handle - You always must create it by
2131 yourself and assign to TCanvas.Handle property manually.
2132 To optimize assembler version, returns Handle value. }
2133 procedure DeselectHandles;
2134 {* Call this method to deselect all graphic tool objects from the canvas. }
2135 property Pixels[ X, Y: Integer ]: TColor read GetPixels write SetPixels;
2136 {* Obvious. }
2137 end;
2138 //[END OF TCanvas DEFINITION]
2140 //[GlobalCanvas_OnTextArea]
2142 GlobalCanvas_OnTextArea : TOnTextArea;
2143 {* Global event to extend Canvas with possible add-ons, applied
2144 when rotated fonts are used only (to take into consideration
2145 Font.Orientation property in TextArea method). }
2147 //[NewCanvas DECLARATION]
2148 function NewCanvas( DC: HDC ): PCanvas;
2149 {* Use to construct Canvas on base of memory DC. }
2151 //[Extended FUNCTIONS TO WORK WITH CANVAS]
2152 {++}(*
2153 {$IFDEF F_P}
2154 function Windows_Polygon(DC: HDC; var Points; Count: Integer): BOOL; stdcall;
2155 function Windows_Polyline(DC: HDC; var Points; Count: Integer): BOOL; stdcall;
2156 function FillRect(hDC: HDC; const lprc: TRect; hbr: HBRUSH): Integer; stdcall;
2157 function OffsetRect(var lprc: TRect; dx, dy: Integer): BOOL; stdcall;
2158 function CreateAcceleratorTable(var Accel; Count: Integer): HACCEL; stdcall;
2159 function TrackPopupMenu(hMenu: HMENU; uFlags: UINT; x, y, nReserved: Integer;
2160 hWnd: HWND; prcRect: PRect): BOOL; stdcall;
2161 function AdjustTokenPrivileges(TokenHandle: THandle; DisableAllPrivileges: BOOL;
2162 const NewState: TTokenPrivileges; BufferLength: DWORD;
2163 var PreviousState: TTokenPrivileges; var ReturnLength: DWORD): BOOL; stdcall;
2164 function InflateRect(var lprc: TRect; dx, dy: Integer): BOOL; stdcall;
2165 {$IFDEF F_P105ORBELOW}
2166 function InvalidateRect(hWnd: HWND; lpRect: PRect; bErase: BOOL): BOOL; stdcall;
2167 function ValidateRect(hWnd: HWND; lpRect: PRect): BOOL; stdcall;
2168 {$ENDIF F_P105ORBELOW}
2169 {$ENDIF}
2170 *){--}
2185 { -- Image list object -- }
2186 //[IMAGE LIST]
2188 type
2189 TImageListColors = (ilcColor,ilcColor4,ilcColor8,ilcColor16,
2190 ilcColor24,ilcColor32,ilcColorDDB,ilcDefault);
2191 {* ImageList color schemes available. }
2193 TDrawingStyles = ( dsBlend25, dsBlend50, dsMask, dsTransparent );
2194 {* ImageList drawing styles available. }
2195 TDrawingStyle = Set of TDrawingStyles;
2196 {* Style of drawing is a combination of all available drawing styles. }
2198 TImageType = (itBitmap,itIcon,itCursor);
2199 {* ImageList types available. }
2201 {++}(*TImageList = class;*){--}
2202 PImageList = {-}^{+}TImageList;
2203 {* }
2205 TImgLOVrlayIdx = 1..15;
2207 { ---------------------------------------------------------------------
2209 TImageList - images container
2211 ----------------------------------------------------------------------- }
2212 //[TImageList DEFINITION]
2213 TImageList = object( TObj )
2214 {* ImageList incapsulation. }
2215 protected
2216 FHandle: THandle;
2217 FControl: Pointer; // PControl;
2218 fPrev, fNext: PImageList;
2219 FColors: TImageListColors;
2220 FMasked: Boolean;
2221 FImgWidth: Integer;
2222 FImgHeight: Integer;
2223 FDrawingStyle: TDrawingStyle;
2224 FBlendColor: TColor;
2225 fBkColor: TColor;
2226 FAllocBy: Integer;
2227 FShareImages: Boolean;
2228 FOverlay: array[ TImgLOVrlayIdx ] of Integer;
2229 function HandleNeeded : Boolean;
2230 procedure SetColors(const Value: TImageListColors);
2231 procedure SetMasked(const Value: Boolean);
2232 procedure SetImgWidth(const Value: Integer);
2233 procedure SetImgHeight(const Value: Integer);
2234 function GetCount: Integer;
2235 function GetBkColor: TColor;
2236 procedure SetBkColor(const Value: TColor);
2237 function GetBitmap: HBitmap;
2238 function GetMask: HBitmap;
2239 function GetDrawStyle : DWord;
2240 procedure SetAllocBy(const Value: Integer);
2241 function GetHandle: THandle;
2242 function GetOverlay(Idx: TImgLOVrlayIdx): Integer;
2243 procedure SetOverlay(Idx: TImgLOVrlayIdx; const Value: Integer);
2244 protected
2245 procedure SetHandle(const Value: THandle);
2247 public
2248 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
2250 property Handle : THandle read GetHandle write SetHandle;
2251 {* Handle of ImageList object. }
2252 property ShareImages : Boolean read FShareImages write FShareImages;
2253 {* True if images are shared between processes (it is set to True,
2254 if its Handle is assigned to given value, which is a handle of
2255 already existing ImageList object). }
2256 property Colors : TImageListColors read FColors write SetColors;
2257 {* Colors used to represent images. }
2258 property Masked : Boolean read FMasked write SetMasked;
2259 {* True, if mask is used. It is set to True, if first added image
2260 is icon, e.g. }
2261 property ImgWidth : Integer read FImgWidth write SetImgWidth;
2262 {* Width of every image in list. If change, ImageList is cleared. }
2263 property ImgHeight : Integer read FImgHeight write SetImgHeight;
2264 {* Height of every image in list. If change, ImageList is cleared. }
2265 property Count : Integer read GetCount;
2266 {* Number of images in list. }
2267 property AllocBy : Integer read FAllocBy write SetAllocBy;
2268 {* Allocation factor. Default is 1. Set it to size of ImageList if this
2269 value is known - to optimize speed of allocation. }
2270 property BkColor : TColor read GetBkColor write SetBkColor;
2271 {* Background color. }
2272 property BlendColor : TColor read FBlendColor write FBlendColor;
2273 {* Blend color. }
2275 property Bitmap : HBitmap read GetBitmap;
2276 {* Bitmap, containing all ImageList images (tiled horizontally). }
2277 property Mask : HBitmap read GetMask;
2278 {* Monochrome bitmap, containing masks for all images in list (if not
2279 Masked, always returns nil). }
2280 function ImgRect( Idx : Integer ) : TRect;
2281 {* Rectangle occupied of given image in ImageList. }
2283 function Add( Bmp, Msk : HBitmap ) : Integer;
2284 {* Adds bitmap and given mask to ImageList. }
2285 function AddMasked( Bmp : HBitmap; Color : TColor ) : Integer;
2286 {* Adds bitmap to ImageList, using given color to create mask. }
2287 function AddIcon( Ico : HIcon ) : Integer;
2288 {* Adds icon to ImageList (always masked). }
2289 procedure Delete( Idx : Integer );
2290 {* Deletes given image from ImageList. }
2291 procedure Clear;
2292 {* Makes ImageList empty. }
2293 function Replace( Idx : Integer; Bmp, Msk : HBitmap ) : Boolean;
2294 {* Replaces given (by index) image with bitmap and its mask with mask bitmap. }
2295 function ReplaceIcon( Idx : Integer; Ico : HIcon ) : Boolean;
2296 {* Replaces given (by index) image with an icon. }
2297 function Merge( Idx : Integer; ImgList2 : PImageList; Idx2 : Integer; X, Y : Integer )
2298 : PImageList;
2299 {* Merges two ImageList objects, returns resulting ImageList. }
2300 function ExtractIcon( Idx : Integer ) : HIcon;
2301 {* Extracts icon by index. }
2302 function ExtractIconEx( Idx : Integer ) : HIcon;
2303 {* Extracts icon (is created using current drawing style). }
2305 property DrawingStyle : TDrawingStyle read FDrawingStyle write FDrawingStyle;
2306 {* Drawing style. }
2307 procedure Draw( Idx : Integer; DC : HDC; X, Y : Integer );
2308 {* Draws given (by index) image from ImageList onto passed Device Context. }
2309 procedure StretchDraw( Idx : Integer; DC : HDC; const Rect : TRect );
2310 {* Draws given image with stratching. }
2312 function LoadBitmap( ResourceName : PChar; TranspColor : TColor ) : Boolean;
2313 {* Loads ImageList from resource. }
2314 //function LoadIcon( ResourceName : PChar ) : Boolean;
2315 //function LoadCursor( ResourceName : PChar ) : Boolean;
2316 function LoadFromFile( FileName : PChar; TranspColor : TColor; ImgType : TImageType ) : Boolean;
2317 {* Loads ImageList from file. }
2318 function LoadSystemIcons( SmallIcons : Boolean ) : Boolean;
2319 {* Assigns ImageList to system icons list (big or small). }
2321 property Overlay[ Idx: TImgLOVrlayIdx ]: Integer read GetOverlay write SetOverlay;
2322 {* Overlay images for image list (images, used as overlay images to draw over
2323 other images from the image list). These overalay images can be used in
2324 listview and treeview as overlaying images (up to four masks at the same
2325 time). }
2326 {$IFDEF USE_CONSTRUCTORS}
2327 constructor CreateImageList( POwner: Pointer );
2328 {$ENDIF USE_CONSTRUCTORS}
2329 end;
2330 //[END OF TImageList DEFINITION]
2332 //[IMAGE LIST API]
2334 const
2335 CLR_NONE = $FFFFFFFF;
2336 CLR_DEFAULT = $FF000000;
2338 type
2339 HImageList = THandle;
2341 const
2342 ILC_MASK = $0001;
2343 ILC_COLOR = $00FE;
2344 ILC_COLORDDB = $00FE;
2345 ILC_COLOR4 = $0004;
2346 ILC_COLOR8 = $0008;
2347 ILC_COLOR16 = $0010;
2348 ILC_COLOR24 = $0018;
2349 ILC_COLOR32 = $0020;
2350 ILC_PALETTE = $0800;
2352 const
2353 ILD_NORMAL = $0000;
2354 ILD_TRANSPARENT = $0001;
2355 ILD_MASK = $0010;
2356 ILD_IMAGE = $0020;
2357 ILD_BLEND25 = $0002;
2358 ILD_BLEND50 = $0004;
2359 ILD_OVERLAYMASK = $0F00;
2361 const
2362 ILD_SELECTED = ILD_BLEND50;
2363 ILD_FOCUS = ILD_BLEND25;
2364 ILD_BLEND = ILD_BLEND50;
2365 CLR_HILIGHT = CLR_DEFAULT;
2367 function ImageList_Create(CX, CY: Integer; Flags: UINT;
2368 Initial, Grow: Integer): HImageList; stdcall;
2369 function ImageList_Destroy(ImageList: HImageList): Bool; stdcall;
2370 function ImageList_GetImageCount(ImageList: HImageList): Integer; stdcall;
2371 function ImageList_SetImageCount(ImageList: HImageList; Count: Integer): Integer; stdcall;
2372 function ImageList_Add(ImageList: HImageList; Image, Mask: HBitmap): Integer; stdcall;
2373 function ImageList_ReplaceIcon(ImageList: HImageList; Index: Integer;
2374 Icon: HIcon): Integer; stdcall;
2375 function ImageList_SetBkColor(ImageList: HImageList; ClrBk: TColorRef): TColorRef; stdcall;
2376 function ImageList_GetBkColor(ImageList: HImageList): TColorRef; stdcall;
2377 function ImageList_SetOverlayImage(ImageList: HImageList; Image: Integer;
2378 Overlay: Integer): Bool; stdcall;
2380 function ImageList_AddIcon(ImageList: HImageList; Icon: HIcon): Integer;
2382 function Index2OverlayMask(Index: Integer): Integer;
2384 function ImageList_Draw(ImageList: HImageList; Index: Integer;
2385 Dest: HDC; X, Y: Integer; Style: UINT): Bool; stdcall;
2387 function ImageList_Replace(ImageList: HImageList; Index: Integer;
2388 Image, Mask: HBitmap): Bool; stdcall;
2389 function ImageList_AddMasked(ImageList: HImageList; Image: HBitmap;
2390 Mask: TColorRef): Integer; stdcall;
2391 function ImageList_DrawEx(ImageList: HImageList; Index: Integer;
2392 Dest: HDC; X, Y, DX, DY: Integer; Bk, Fg: TColorRef; Style: Cardinal): Bool; stdcall;
2393 function ImageList_Remove(ImageList: HImageList; Index: Integer): Bool; stdcall;
2394 function ImageList_GetIcon(ImageList: HImageList; Index: Integer;
2395 Flags: Cardinal): HIcon; stdcall;
2396 function ImageList_LoadImageA(Instance: THandle; Bmp: PAnsiChar; CX, Grow: Integer;
2397 Mask: TColorRef; pType, Flags: Cardinal): HImageList; stdcall;
2398 function ImageList_LoadImageW(Instance: THandle; Bmp: PWideChar; CX, Grow: Integer;
2399 Mask: TColorRef; pType, Flags: Cardinal): HImageList; stdcall;
2400 function ImageList_LoadImage(Instance: THandle; Bmp: PChar; CX, Grow: Integer;
2401 Mask: TColorRef; pType, Flags: Cardinal): HImageList; stdcall;
2402 function ImageList_BeginDrag(ImageList: HImageList; Track: Integer;
2403 XHotSpot, YHotSpot: Integer): Bool; stdcall;
2404 function ImageList_EndDrag: Bool; stdcall;
2405 function ImageList_DragEnter(LockWnd: HWnd; X, Y: Integer): Bool; stdcall;
2406 function ImageList_DragLeave(LockWnd: HWnd): Bool; stdcall;
2407 function ImageList_DragMove(X, Y: Integer): Bool; stdcall;
2408 function ImageList_SetDragCursorImage(ImageList: HImageList; Drag: Integer;
2409 XHotSpot, YHotSpot: Integer): Bool; stdcall;
2410 function ImageList_DragShowNolock(Show: Bool): Bool; stdcall;
2411 function ImageList_GetDragImage(Point, HotSpot: PPoint): HImageList; stdcall;
2413 { macros }
2414 procedure ImageList_RemoveAll(ImageList: HImageList); stdcall;
2415 function ImageList_ExtractIcon(Instance: THandle; ImageList: HImageList;
2416 Image: Integer): HIcon; stdcall;
2417 function ImageList_LoadBitmap(Instance: THandle; Bmp: PChar;
2418 CX, Grow: Integer; MasK: TColorRef): HImageList; stdcall;
2420 //function ImageList_Read(Stream: IStream): HImageList; stdcall;
2421 //function ImageList_Write(ImageList: HImageList; Stream: IStream): BOOL; stdcall;
2423 //[TImageInfo]
2424 type
2425 PImageInfo = ^TImageInfo;
2426 TImageInfo = packed record
2427 hbmImage: HBitmap;
2428 hbmMask: HBitmap;
2429 Unused1: Integer;
2430 Unused2: Integer;
2431 rcImage: TRect;
2432 end;
2434 function ImageList_GetIconSize(ImageList: HImageList; var CX, CY: Integer): Bool; stdcall;
2435 function ImageList_SetIconSize(ImageList: HImageList; CX, CY: Integer): Bool; stdcall;
2436 function ImageList_GetImageInfo(ImageList: HImageList; Index: Integer;
2437 var ImageInfo: TImageInfo): Bool; stdcall;
2438 function ImageList_Merge(ImageList1: HImageList; Index1: Integer;
2439 ImageList2: HImageList; Index2: Integer; DX, DY: Integer)://Bool - ERROR IN VCL
2440 HImageList; stdcall;
2442 //[LoadBmp]
2443 function LoadBmp( Instance: Integer; Rsrc: PChar; MasterObj: PObj ): HBitmap;
2458 //[BITMAPS]
2459 type
2460 tagBitmap = Windows.TBitmap;
2462 TPixelFormat = ( pfDevice, pf1bit, pf4bit, pf8bit, pf15bit, pf16bit, pf24bit,
2463 pf32bit, pfCustom );
2464 {* Available pixel formats. }
2465 TBitmapHandleType = ( bmDIB, bmDDB );
2466 {* Available bitmap handle types. }
2468 {++}(*TBitmap = class;*){--}
2469 PBitmap = {-}^{+}TBitmap;
2470 { ----------------------------------------------------------------------
2472 TBitmap - bitmap image
2474 ----------------------------------------------------------------------- }
2475 //[TBitmap DEFINITION]
2476 TBitmap = object( TObj )
2477 {* Bitmap incapsulation object. }
2478 protected
2479 fHeight: Integer;
2480 fWidth: Integer;
2481 fHandle: HBitmap;
2482 fCanvas: PCanvas;
2483 fScanLineSize: Integer;
2484 fBkColor: TColor;
2485 fApplyBkColor2Canvas: procedure( Sender: PBitmap );
2486 fDetachCanvas: procedure( Sender: PBitmap );
2487 fCanvasAttached : Integer;
2488 fHandleType: TBitmapHandleType;
2489 fDIBHeader: PBitmapInfo;
2490 fDIBBits: Pointer;
2491 fDIBSize: Integer;
2492 fNewPixelFormat: TPixelFormat;
2493 fFillWithBkColor: procedure( BmpObj: PBitmap; DC: HDC; oldW, oldH: Integer );
2494 //stdcall;
2495 fTransMaskBmp: PBitmap;
2496 fTransColor: TColor;
2497 fGetDIBPixels: function( Bmp: PBitmap; X, Y: Integer ): TColor;
2498 fSetDIBPixels: procedure( Bmp: PBitmap; X, Y: Integer; Value: TColor );
2499 fScanLine0: PByte;
2500 fScanLineDelta: Integer;
2501 fPixelMask: DWORD;
2502 fPixelsPerByteMask: Integer;
2503 fBytesPerPixel: Integer;
2504 fDIBAutoFree: Boolean;
2505 procedure SetHeight(const Value: Integer);
2506 procedure SetWidth(const Value: Integer);
2507 function GetEmpty: Boolean;
2508 function GetHandle: HBitmap;
2509 function GetHandleAllocated: Boolean;
2510 procedure SetHandle(const Value: HBitmap);
2511 procedure SetPixelFormat(Value: TPixelFormat);
2512 procedure FormatChanged;
2513 function GetCanvas: PCanvas;
2514 procedure CanvasChanged( Sender: PObj );
2515 function GetScanLine(Y: Integer): Pointer;
2516 function GetScanLineSize: Integer;
2517 procedure ClearData;
2518 procedure ClearTransImage;
2519 procedure SetBkColor(const Value: TColor);
2520 function GetDIBPalEntries(Idx: Integer): TColor;
2521 function GetDIBPalEntryCount: Integer;
2522 procedure SetDIBPalEntries(Idx: Integer; const Value: TColor);
2523 procedure SetHandleType(const Value: TBitmapHandleType);
2524 function GetPixelFormat: TPixelFormat;
2525 function GetPixels(X, Y: Integer): TColor;
2526 procedure SetPixels(X, Y: Integer; const Value: TColor);
2527 function GetDIBPixels(X, Y: Integer): TColor;
2528 procedure SetDIBPixels(X, Y: Integer; const Value: TColor);
2529 function GetBoundsRect: TRect;
2530 protected
2531 {++}(*public*){--}
2532 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
2533 public
2534 property Width: Integer read fWidth write SetWidth;
2535 {* Width of bitmap. To make code smaller, avoid changing Width or Height
2536 after bitmap is created (using NewBitmap) or after it is loaded from
2537 file, stream of resource. }
2538 property Height: Integer read fHeight write SetHeight;
2539 {* Height of bitmap. To make code smaller, avoid changing Width or Height
2540 after bitmap is created (using NewBitmap) or after it is loaded from
2541 file, stream of resource. }
2542 property BoundsRect: TRect read GetBoundsRect;
2543 {* Returns rectangle (0,0,Width,Height). }
2544 property Empty: Boolean read GetEmpty;
2545 {* Returns True if Width or Height is 0. }
2546 procedure Clear;
2547 {* Makes bitmap empty, setting its Width and Height to 0. }
2548 procedure LoadFromFile( const Filename: String );
2549 {* Loads bitmap from file (LoadFromStream used). }
2550 function LoadFromFileEx( const Filename: String ): Boolean;
2551 {* Loads bitmap from a file. If necessary, bitmap is RLE-decoded. Code given
2552 by Vyacheslav A. Gavrik. }
2553 procedure SaveToFile( const Filename: String );
2554 {* Stores bitmap to file (SaveToStream used). }
2555 procedure LoadFromStream( Strm: PStream );
2556 {* Loads bitmap from stream. Follow loading, bitmap has DIB format (without
2557 handle allocated). It is possible to draw DIB bitmap without creating
2558 handle for it, which can economy GDI resources. }
2559 function LoadFromStreamEx( Strm: PStream ): Boolean;
2560 {* Loads bitmap from a stream. Difference is that RLE decoding supported.
2561 Code given by Vyacheslav A. Gavrik. }
2562 procedure SaveToStream( Strm: PStream );
2563 {* Saves bitmap to stream. If bitmap is not DIB, it is converted to DIB
2564 before saving. }
2565 procedure LoadFromResourceID( Inst: DWORD; ResID: Integer );
2566 {* Loads bitmap from resource using integer ID of resource. To load by name,
2567 use LoadFromResurceName. To load resource of application itself, pass
2568 hInstance as first parameter. This method also can be used to load system
2569 predefined bitmaps, if 0 is passed as Inst parameter:
2570 |<pre>
2571 OBM_BTNCORNERS OBM_REDUCE
2572 OBM_BTSIZE OBM_REDUCED
2573 OBM_CHECK OBM_RESTORE
2574 OBM_CHECKBOXES OBM_RESTORED
2575 OBM_CLOSE OBM_RGARROW
2576 OBM_COMBO OBM_RGARROWD
2577 OBM_DNARROW OBM_RGARROWI
2578 OBM_DNARROWD OBM_SIZE
2579 OBM_DNARROWI OBM_UPARROW
2580 OBM_LFARROW OBM_UPARROWD
2581 OBM_LFARROWD OBM_UPARROWI
2582 OBM_LFARROWI OBM_ZOOM
2583 OBM_MNARROW OBM_ZOOMD
2584 |</pre> }
2585 procedure LoadFromResourceName( Inst: DWORD; ResName: PChar );
2586 {* Loads bitmap from resurce (using passed name of bitmap resource. }
2587 function Assign( SrcBmp: PBitmap ): Boolean;
2588 {* Assigns bitmap from another. Returns False if not success.
2589 Note: remember, that Canvas is not assigned - only bitmap image
2590 is copied. And for DIB, handle is not allocating due this process. }
2591 property Handle: HBitmap read GetHandle write SetHandle;
2592 {* Handle of bitmap. Created whenever property accessed. To check if handle
2593 is allocated (without allocating it), use HandleAllocated property. }
2594 property HandleAllocated: Boolean read GetHandleAllocated;
2595 {* Returns True, if Handle already allocated. }
2596 function ReleaseHandle: HBitmap;
2597 {* Returns Handle and releases it, so bitmap no more know about handle.
2598 This method does not destroy bitmap image, but converts it into DIB.
2599 Returned Handle actually is a handle of copy of original bitmap. If
2600 You need not in keping it up, use Dormant method instead. }
2601 procedure Dormant;
2602 {* Releases handle from bitmap and destroys it. But image is not destroyed
2603 and its data are preserved in DIB format. Please note, that in KOL, DIB
2604 bitmaps can be drawn onto given device context without allocating of
2605 handle. So, it is very useful to call Dormant preparing it using
2606 Canvas drawing operations - to economy GDI resources. }
2607 property HandleType: TBitmapHandleType read fHandleType write SetHandleType;
2608 {* bmDIB, if DIB part of image data is filled and stored internally in
2609 TBitmap object. DIB image therefore can have Handle allocated, which
2610 require resources. Use HandleAllocated funtion to determine if handle
2611 is allocated and Dormant method to remove it, if You want to economy
2612 GDI resources. (Actually Handle needed for DIB bitmap only in case
2613 when Canvas is used to draw on bitmap surface). Please note also, that
2614 before saving bitmap to file or stream, it is converted to DIB. }
2615 property PixelFormat: TPixelFormat read GetPixelFormat write SetPixelFormat;
2616 {* Current pixel format. If format of bitmap is unknown, or bitmap is DDB,
2617 value is pfDevice. Setting PixelFormat to any other format converts
2618 bitmap to DIB, back to pfDevice converts bitmap to DDB again. Avoid
2619 such conversations for large bitmaps or for numerous bitmaps in your
2620 application to keep good performance. }
2621 function BitsPerPixel: Integer;
2622 {* Returns bits per pixel if possible. }
2623 procedure Draw( DC: HDC; X, Y: Integer );
2624 {* Draws bitmap to given device context. If bitmap is DIB, it is always
2625 drawing using SetDIBitsToDevice API call, which does not require bitmap
2626 handle (so, it is very sensible to call Dormant method to free correspondent
2627 GDI resources). }
2628 procedure StretchDraw( DC: HDC; const Rect: TRect );
2629 {* Draws bitmap onto DC, stretching it to fit given rectangle Rect. }
2630 procedure DrawTransparent( DC: HDC; X, Y: Integer; TranspColor: TColor );
2631 {* Draws bitmap onto DC transparently, using TranspColor as transparent. }
2632 procedure StretchDrawTransparent( DC: HDC; const Rect: TRect; TranspColor: TColor );
2633 {* Draws bitmap onto given rectangle of destination DC (with stretching it
2634 to fit Rect) - transparently, using TranspColor as transparent. }
2635 procedure DrawMasked( DC: HDC; X, Y: Integer; Mask: HBitmap );
2636 {* Draws bitmap to destination DC transparently by mask. It is possible
2637 to pass as a mask handle of another TBitmap, previously converted to
2638 monochrome mask using Convert2Mask method. }
2639 procedure StretchDrawMasked( DC: HDC; const Rect: TRect; Mask: HBitmap );
2640 {* Like DrawMasked, but with stretching image onto given rectangle. }
2641 procedure Convert2Mask( TranspColor: TColor );
2642 {* Converts bitmap to monochrome (mask) bitmap with TranspColor replaced
2643 to clBlack and all other ones to clWhite. Such mask bitmap can be used
2644 to draw original bitmap transparently, with given TranspColor as
2645 transparent. (To preserve original bitmap, create new instance of
2646 TBitmap and assign original bitmap to it). See also DrawTransparent and
2647 StretchDrawTransparent methods. }
2648 procedure Invert;
2649 {* Obvious. }
2650 property Canvas: PCanvas read GetCanvas;
2651 {* Canvas can be used to draw onto bitmap. Whenever it is accessed, handle
2652 is allocated for bitmap, if it is not yet (to make it possible
2653 to select bitmap to display compatible device context). }
2654 procedure RemoveCanvas;
2655 {* Call this method to destroy Canvas and free GDI resources. }
2656 property BkColor: TColor read fBkColor write SetBkColor;
2657 {* Used to fill background for Bitmap, when its width or height is increased.
2658 Although this value always synchronized with Canvas.Brush.Color, use it
2659 instead if You do not use Canvas for drawing on bitmap surface. }
2660 property Pixels[ X, Y: Integer ]: TColor read GetPixels write SetPixels;
2661 {* Allows to obtain or change certain pixels of a bitmap. This method is
2662 both for DIB and DDB bitmaps, and leads to allocate handle anyway. For
2663 DIB bitmaps, it is possible to use property DIBPixels[ ] instead,
2664 which is much faster and does not require in Handle. }
2665 property ScanLineSize: Integer read GetScanLineSize;
2666 {* Returns size of scan line in bytes. Use it to measure size of a single
2667 ScanLine. To calculate increment value from first byte of ScanLine to
2668 first byte of next ScanLine, use difference
2669 ! Integer(ScanLine[1]-ScanLine[0])
2670 (this is because bitmap can be oriented from bottom to top, so
2671 step can be negative). }
2672 property ScanLine[ Y: Integer ]: Pointer read GetScanLine;
2673 {* Use ScanLine to access DIB bitmap pixels in memory to direct access it
2674 fast. Take in attention, that for different pixel formats, different
2675 bit counts are used to represent bitmap pixels. Also do not forget, that
2676 for formats pf4bit and pf8bit, pixels actually are indices to palette
2677 entries, and for formats pf16bit, pf24bit and pf32bit are actually
2678 RGB values (for pf16bit B:5-G:6-R:5, for pf15bit B:5-G:5-R:5 (high order
2679 bit not used), for pf24bit B:8-G:8-R:8, and for pf32bit high order byte
2680 of TRGBQuad structure is not used). }
2681 property DIBPixels[ X, Y: Integer ]: TColor read GetDIBPixels write SetDIBPixels;
2682 {* Allows direct access to pixels of DIB bitmap, faster then Pixels[ ]
2683 property. Access to read is slower for pf15bit, pf16bit formats (because
2684 some conversation needed to translate packed RGB color to TColor). And
2685 for write, operation performed most slower for pf4bit, pf8bit (searching
2686 nearest color required) and fastest for pf24bit, pf32bit and pf1bit. }
2687 property DIBPalEntryCount: Integer read GetDIBPalEntryCount;
2688 {* Returns palette entries count for DIB image. Always returns 2 for pf1bit,
2689 16 for pf4bit, 256 for pf8bit and 0 for other pixel formats. }
2690 property DIBPalEntries[ Idx: Integer ]: TColor read GetDIBPalEntries write
2691 SetDIBPalEntries;
2692 {* Provides direct access to DIB palette. }
2693 function DIBPalNearestEntry( Color: TColor ): Integer;
2694 {* Returns index of entry in DIB palette with color nearest (or matching)
2695 to given one. }
2696 property DIBBits: Pointer read fDIBBits;
2697 {* This property is mainly for internal use. }
2698 property DIBSize: Integer read fDIBSize;
2699 {* Size of DIBBits array. }
2700 property DIBHeader: PBitmapInfo read fDIBHeader;
2701 {* This property is mainly for internal use. }
2702 procedure DIBDrawRect( DC: HDC; X, Y: Integer; const R: TRect );
2703 {* This procedure copies given rectangle to the target device context,
2704 but only for DIB bitmap (using SetDIBBitsToDevice API call). }
2705 procedure RotateRight;
2706 {* Rotates bitmap right (90 degree). Bitmap must be DIB. If You definitevely
2707 know format of a bitmap, use instead one of methods RotateRightMono,
2708 RotateRight4bit, RotateRight8bit, RotateRight16bit or RotateRightTrueColor
2709 - this will economy code. But if for most of formats such methods are
2710 called, this can be more economy just to call always universal method
2711 RotateRight. }
2712 procedure RotateLeft;
2713 {* Rotates bitmap left (90 degree). Bitmap must be DIB. If You definitevely
2714 know format of a bitmap, use instead one of methods RotateLeftMono,
2715 RotateLeft4bit, RotateLeft8bit, RotateLeft16bit or RotateLeftTrueColor
2716 - this will economy code. But if for most of formats such methods are
2717 called, this can be more economy just to call always universal method
2718 RotateLeft. }
2719 procedure RotateRightMono;
2720 {* Rotates bitmat right, but only if bitmap is monochrome (pf1bit). }
2721 procedure RotateLeftMono;
2722 {* Rotates bitmap left, but only if bitmap is monochrome (pf1bit). }
2723 procedure RotateRight4bit;
2724 {* Rotates bitmap right, but only if PixelFormat is pf4bit. }
2725 procedure RotateLeft4bit;
2726 {* Rotates bitmap left, but only if PixelFormat is pf4bit. }
2727 procedure RotateRight8bit;
2728 {* Rotates bitmap right, but only if PixelFormat is pf8bit. }
2729 procedure RotateLeft8bit;
2730 {* Rotates bitmap left, but only if PixelFormat is pf8bit. }
2731 procedure RotateRight16bit;
2732 {* Rotates bitmap right, but only if PixelFormat is pf16bit. }
2733 procedure RotateLeft16bit;
2734 {* Rotates bitmap left, but only if PixelFormat is pf16bit. }
2735 procedure RotateRightTrueColor;
2736 {* Rotates bitmap right, but only if PixelFormat is pf24bit or pf32bit. }
2737 procedure RotateLeftTrueColor;
2738 {* Rotates bitmap left, but only if PixelFormat is pf24bit or pf32bit. }
2739 procedure FlipVertical;
2740 {* Flips bitmap vertically }
2741 procedure FlipHorizontal;
2742 {* Flips bitmap horizontally }
2743 procedure CopyRect( const DstRect : TRect; SrcBmp : PBitmap; const SrcRect : TRect );
2744 {* It is possible to use Canvas.CopyRect for such purpose, but if You
2745 do not want use TCanvas, it is possible to copy rectangle from one
2746 bitmap to another using this function. }
2747 function CopyToClipboard: Boolean;
2748 {* Copies bitmap to clipboard. }
2749 function PasteFromClipboard: Boolean;
2750 {* Takes CF_DIB format bitmap from clipboard and assigns it to the
2751 TBitmap object. }
2752 end;
2753 //[END OF TBitmap DEFINITION]
2755 //[NewBitmap DECLARATION]
2756 function NewBitmap( W, H: Integer ): PBitmap;
2757 {* Creates bitmap object of given size. If it is possible, do not change its
2758 size (Width and Heigth) later - this can economy code a bit. See TBitmap. }
2760 function NewDIBBitmap( W, H: Integer; PixelFormat: TPixelFormat ): PBitmap;
2761 {* Creates DIB bitmap object of given size and pixel format. If it is possible,
2762 do not change its size (Width and Heigth) later - this can economy code a bit.
2763 See TBitmap. }
2765 //[CalcScanLineSize DECLARATION]
2766 function CalcScanLineSize( Header: PBitmapInfoHeader ): Integer;
2767 {* May be will be useful. }
2769 //[DefaultPixelFormat VARIABLE]
2771 //DefaultBitsPerPixel: Integer = 16;
2772 DefaultPixelFormat: TPixelFormat = pf16bit;
2774 //[Mapped bitmaps]
2776 { -- Function to load bitmap mapping some its colors. -- }
2777 function LoadMappedBitmap( hInst: THandle; BmpResID: Integer; const Map: array of TColor )
2778 : HBitmap;
2779 {* This function can be used to load bitmap and replace some it colors to
2780 desired ones. This function especially useful when loaded by the such way
2781 bitmap is used as toolbar bitmap - to replace some original colors to
2782 system default colors. To use this function properly, the bitmap shoud
2783 be prepared as 16-color bitmap, which uses only system colors. To do so,
2784 create a new 16-color bitmap with needed dimensions in Borland Image Editor
2785 and paste a bitmap image, copyed in another graphic tool, and then save it.
2786 If this is not done, bitmap will not be loaded correctly! }
2787 function LoadMappedBitmapEx( MasterObj: PObj; hInst: THandle; BmpResName: PChar; const Map: array of TColor )
2788 : HBitmap;
2789 {* Like LoadMappedBitmap, but much powerful. It uses CreateMappedBitmapEx
2790 by Alex Pravdin, so it understands any bitmap color format, including
2791 pf24bit. Also, LoadMappedBitmapEx provides auto-destroying loaded resource
2792 when MasterObj is destroyed. }
2793 function CreateMappedBitmap(Instance: THandle; Bitmap: Integer;
2794 Flags: UINT; ColorMap: PColorMap; NumMaps: Integer): HBitmap; stdcall;
2795 {* Creates mapped bitmap replacing colors correspondently to the
2796 ColorMap (each pare of colors defines color replaced and a color
2797 used for replace it in the bitmap). See also CreateMappedBitmapEx. }
2798 function CreateMappedBitmapEx(Instance: THandle; BmpRsrcName: PChar; Flags:
2799 Cardinal; ColorMap: PColorMap; NumMaps: Integer): HBitmap;
2800 {* By Alex Pravdin.
2801 Creates mapped bitmap independently from bitmap color format (works
2802 correctly with bitmaps having format deeper than 8bit per pixel). }
2815 //[ICONS]
2817 type
2818 {++}(*TIcon = class;*){--}
2819 PIcon = {-}^{+}TIcon;
2820 { ----------------------------------------------------------------------
2822 TIcon - icon image
2824 ----------------------------------------------------------------------- }
2825 //[TIcon DEFINITION]
2826 TIcon = object( TObj )
2827 {* Object type to incapsulate icon or cursor image. }
2828 protected
2829 FSize : Integer;
2830 FHandle: HIcon;
2831 FShareIcon: Boolean;
2832 procedure SetSize(const Value: Integer);
2833 procedure SetHandle(const Value: HIcon);
2834 function GetHotSpot: TPoint;
2835 function GetEmpty: Boolean;
2836 protected
2837 {++}(*public*){--}
2838 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
2839 public
2840 property Size : Integer read FSize write SetSize;
2841 {* Icon dimension (width and/or height, which are equal to each other always). }
2842 property Handle : HIcon read FHandle write SetHandle;
2843 {* Windows icon object handle. }
2844 procedure Clear;
2845 {* Clears icon, freeing image and allocated GDI resource (Handle). }
2846 property Empty: Boolean read GetEmpty;
2847 {* Returns True if icon is Empty. }
2848 property ShareIcon : Boolean read FShareIcon write FShareIcon;
2849 {* True, if icon object is shared and can not be deleted when TIcon object
2850 is destroyed (set this flag is to True, if an icon is obtained from another
2851 TIcon object, for example). }
2852 property HotSpot : TPoint read GetHotSpot;
2853 {* Hot spot point - for cursors. }
2854 procedure Draw( DC : HDC; X, Y : Integer );
2855 {* Draws icon onto given device context. Icon always is drawn transparently
2856 using its transparency mask (stored internally in icon object). }
2857 procedure StretchDraw( DC : HDC; Dest : TRect );
2858 {* Draws icon onto given device context with stretching it to fit destination
2859 rectangle. See also Draw. }
2860 procedure LoadFromStream( Strm : PStream );
2861 {* Loads icon from stream. If stream contains several icons (of
2862 different dimentions), icon with the most appropriate size is loading. }
2863 procedure LoadFromFile( const FileName : String );
2864 {* Load icon from file. If file contains several icons (of
2865 different dimensions), icon with the most appropriate size is loading. }
2866 procedure LoadFromResourceID( Inst: Integer; ResID: Integer; DesiredSize: Integer );
2867 {* Loads icon from resource. To load system default icon, pass 0 as Inst and
2868 one of followin values as ResID:
2869 |<pre>
2870 IDI_APPLICATION Default application icon.
2871 IDI_ASTERISK Asterisk (used in informative messages).
2872 IDI_EXCLAMATION Exclamation point (used in warning messages).
2873 IDI_HAND Hand-shaped icon (used in serious warning messages).
2874 IDI_QUESTION Question mark (used in prompting messages).
2875 IDI_WINLOGO Windows logo.
2876 |</pre> It is also possible to load icon from resources of another module,
2877 if pass instance handle of loaded module as Inst parameter. }
2878 procedure LoadFromResourceName( Inst: Integer; ResName: PChar; DesiredSize: Integer );
2879 {* Loads icon from resource. To load own application resource, pass
2880 hInstance as Inst parameter. It is possible to load resource from
2881 another module, if pass its instance handle as Inst. }
2882 procedure LoadFromExecutable( const FileName: String; IconIdx: Integer );
2883 {* Loads icon from executable (exe or dll file). Always default sized icon
2884 is loaded. It is possible also to get know how much icons are contained
2885 in executable using gloabl function GetFileIconCount. To obtain icon of
2886 another size, try to load given executable and use LoadFromResourceID
2887 method. }
2888 procedure SaveToStream( Strm : PStream );
2889 {* Saves single icon to stream. To save icons with several different
2890 dimensions, use global procedure SaveIcons2Stream. }
2891 procedure SaveToFile( const FileName : String );
2892 {* Saves single icon to file. To save icons with several different
2893 dimensions, use global procedure SaveIcons2File. }
2894 function Convert2Bitmap( TranColor: TColor ): HBitmap;
2895 {* Converts icon to bitmap, returning Windows GDI bitmap resource as
2896 a result. It is possible later to assign returned bitmap handle to
2897 Handle property of TBitmap object to use features of TBitmap.
2898 Pass TranColor to replace transparent area of icon with given color. }
2899 end;
2900 //[END OF TIcon DEFINITION]
2902 //[Icon save functions]
2904 procedure SaveIcons2Stream( const Icons : array of PIcon; Strm : PStream );
2905 {* Saves several icons (of different dimentions) to stream. }
2906 function SaveIcons2StreamEx( const BmpHandles: array of HBitmap; Strm: PStream ): Boolean;
2907 {* Saves icons creating it from pairs of bitmaps and their masks.
2908 BmpHandles array must contain pairs of bitmap handles, each pair
2909 of color bitmap and mask bitmap of the same size. }
2910 procedure SaveIcons2File( const Icons : array of PIcon; const FileName : String );
2911 {* Saves several icons (of different dimentions) to file. (Single file
2912 with extension .ico can contain several different sized icon images
2913 to use later one with the most appropriate size). }
2915 //[NewIcon DECLARATION]
2916 function NewIcon: PIcon;
2917 {* Creates new icon object, setting its Size to 32 by default. Created icon
2918 is Empty. }
2920 //[GetFileIconCount DECLARATION]
2921 function GetFileIconCount( const FileName: String ): Integer;
2922 {* Returns number of icon resources stored in given (executable) file. }
2924 //[ICON STRUCTURES]
2925 type
2926 TIconHeader = packed record
2927 idReserved: Word; (* Always set to 0 *)
2928 idType: Word; (* Always set to 1 *)
2929 idCount: Word; (* Number of icon images *)
2930 (* immediately followed by idCount TIconDirEntries *)
2931 end;
2933 TIconDirEntry = packed record
2934 bWidth: Byte; (* Width *)
2935 bHeight: Byte; (* Height *)
2936 bColorCount: Byte; (* Nr. of colors used, see below *)
2937 bReserved: Byte; (* not used, 0 *)
2938 wPlanes: Word; (* not used, 0 *)
2939 wBitCount: Word; (* not used, 0 *)
2940 dwBytesInRes: Longint; (* total number of bytes in images *)
2941 dwImageOffset: Longint;(* location of image from the beginning of file *)
2942 end;
2944 //[LoadImgIcon DECLARATION]
2945 function LoadImgIcon( RsrcName: PChar; Size: Integer ): HIcon;
2946 {* Loads icon of specified size from the resource. }
2955 //[METAFILES]
2957 type
2958 {++}(*TMetafile = class;*){--}
2959 PMetafile = {-}^{+}TMetafile;
2960 { ----------------------------------------------------------------------
2962 TMetafile - Windows metafile and Enchanced Metafile image
2964 ----------------------------------------------------------------------- }
2965 //[TMetafile DEFINITION]
2966 TMetafile = object( TObj )
2967 {* Object type to incapsulate metafile image. }
2968 protected
2969 function GetHeight: Integer;
2970 function GetWidth: Integer;
2971 procedure SetHandle(const Value: THandle);
2972 protected
2973 fHandle: THandle;
2974 fHeader: PEnhMetaHeader;
2975 procedure RetrieveHeader;
2976 public
2977 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
2978 {* }
2979 procedure Clear;
2980 {* }
2981 function Empty: Boolean;
2982 {* Returns TRUE if empty}
2983 property Handle: THandle read fHandle write SetHandle;
2984 {* Returns handle of enchanced metafile. }
2985 function LoadFromStream( Strm: PStream ): Boolean;
2986 {* Loads emf or wmf file format from stream. }
2987 function LoadFromFile( const Filename: String ): Boolean;
2988 {* Loads emf or wmf from stream. }
2989 procedure Draw( DC: HDC; X, Y: Integer );
2990 {* Draws enchanced metafile on DC. }
2991 procedure StretchDraw( DC: HDC; const R: TRect );
2992 {* Draws enchanced metafile stretched. }
2993 property Width: Integer read GetWidth;
2994 {* Native width of the metafile. }
2995 property Height: Integer read GetHeight;
2996 {* Native height of the metafile. }
2997 end;
2998 //[END OF TMetafile DEFINITION]
3000 //[NewMetafile DECLARATION]
3001 function NewMetafile: PMetafile;
3002 {* Creates metafile object. }
3004 //[Metafile CONSTANTS, STRUCTURES, ETC.]
3005 const
3006 WMFKey = Integer($9AC6CDD7);
3007 WMFWord = $CDD7;
3008 type
3009 TMetafileHeader = packed record
3010 Key: Longint;
3011 Handle: SmallInt;
3012 Box: TSmallRect;
3013 Inch: Word;
3014 Reserved: Longint;
3015 CheckSum: Word;
3016 end;
3018 function ComputeAldusChecksum(var WMF: TMetafileHeader): Word;
3020 {++}(*
3021 function SetEnhMetaFileBits(p1: UINT; p2: PChar): HENHMETAFILE; stdcall;
3022 function PlayEnhMetaFile(DC: HDC; p2: HENHMETAFILE; const p3: TRect): BOOL; stdcall;
3023 *){--}
3043 ////////////////////////////////////////////////////////////////////////////////
3044 // UNIVERSAL CONTROL OBJECT //
3045 ////////////////////////////////////////////////////////////////////////////////
3047 //[CM_XXX CONSTANTS]
3049 const
3050 CM_EXECPROC = $8FFF;
3051 CM_BASE = $B000;
3052 CM_ACTIVATE = CM_BASE + 0;
3053 CM_DEACTIVATE = CM_BASE + 1;
3054 CM_ENTER = CM_BASE + 2;
3055 CM_RELEASE = CM_BASE + 3;
3056 CM_QUIT = CM_BASE + 4;
3057 CM_COMMAND = CM_BASE + 5;
3058 CM_MEASUREITEM = CM_BASE + 6;
3059 CM_DRAWITEM = CM_BASE + 7;
3060 CM_TRAYICON = CM_BASE + 8;
3061 CM_INVALIDATE = CM_BASE + 9;
3062 CM_UPDATE = CM_BASE + 10;
3063 CM_NCUPDATE = CM_BASE + 11;
3064 CM_SIZEPOS = CM_BASE + 12;
3065 CM_SIZE = CM_BASE + 13;
3066 CM_SETFOCUS = CM_BASE + 14;
3067 CM_CBN_SELCHANGE = 15;
3069 CM_UIACTIVATE = CM_BASE + 16;
3070 CM_UIDEACTIVATE = CM_BASE + 17;
3071 CM_PROCESS = CM_BASE + 18;
3072 CM_SHOW = CM_BASE + 19;
3074 //CM_CLOSE = CM_BASE + 20;
3075 CM_MDIClientShowEdge = CM_BASE + 21;
3077 //[CN_XXX CONSTANTS]
3079 CN_BASE = $BC00;
3080 CN_CHARTOITEM = CN_BASE + WM_CHARTOITEM;
3081 CN_COMMAND = CN_BASE + WM_COMMAND;
3082 CN_COMPAREITEM = CN_BASE + WM_COMPAREITEM;
3084 CN_CTLCOLORMSGBOX = CN_BASE + WM_CTLCOLORMSGBOX;
3085 CN_CTLCOLOREDIT = CN_BASE + WM_CTLCOLOREDIT;
3086 CN_CTLCOLORLISTBOX = CN_BASE + WM_CTLCOLORLISTBOX;
3087 CN_CTLCOLORBTN = CN_BASE + WM_CTLCOLORBTN;
3088 CN_CTLCOLORDLG = CN_BASE + WM_CTLCOLORDLG;
3089 CN_CTLCOLORSCROLLBAR = CN_BASE + WM_CTLCOLORSCROLLBAR;
3090 CN_CTLCOLORSTATIC = CN_BASE + WM_CTLCOLORSTATIC;
3092 CN_DELETEITEM = CN_BASE + WM_DELETEITEM;
3093 CN_DRAWITEM = CN_BASE + WM_DRAWITEM;
3094 CN_HSCROLL = CN_BASE + WM_HSCROLL;
3095 CN_MEASUREITEM = CN_BASE + WM_MEASUREITEM;
3096 CN_PARENTNOTIFY = CN_BASE + WM_PARENTNOTIFY;
3097 CN_VKEYTOITEM = CN_BASE + WM_VKEYTOITEM;
3098 CN_VSCROLL = CN_BASE + WM_VSCROLL;
3099 CN_KEYDOWN = CN_BASE + WM_KEYDOWN;
3100 CN_KEYUP = CN_BASE + WM_KEYUP;
3101 CN_CHAR = CN_BASE + WM_CHAR;
3102 CN_SYSKEYDOWN = CN_BASE + WM_SYSKEYDOWN;
3103 CN_SYSCHAR = CN_BASE + WM_SYSCHAR;
3104 CN_NOTIFY = CN_BASE + WM_NOTIFY;
3107 //[ID_SELF DEFINED]
3108 ID_SELF: array[ 0..5 ] of Char = ( 'S','E','L','F','_',#0 );
3109 {* Identifier for window property "Self", stored directly in window, when
3110 it is created. This property is used to [fast] find TControl object,
3111 correspondent to given window handle (using API call GetProp). }
3113 //[ID_PREVPROC DEFINED]
3114 ID_PREVPROC: array[ 0..9 ] of Char = ( 'P','R','E','V','_','P','R','O','C',#0 );
3115 {* }
3117 //[MK_ALT DEFINED]
3118 MK_ALT = $20;
3120 //[RICHEDIT STRUCTURES]
3121 type
3122 TCharFormat2A = packed record
3123 cbSize: UINT;
3124 dwMask: DWORD;
3125 dwEffects: DWORD;
3126 yHeight: Longint;
3127 yOffset: Longint;
3128 crTextColor: TColorRef;
3129 bCharSet: Byte;
3130 bPitchAndFamily: Byte;
3131 szFaceName: array[0..LF_FACESIZE - 1] of AnsiChar;
3132 R2Bytes: Word;
3133 wWeight: Word; { Font weight (LOGFONT value) }
3134 sSpacing: Smallint; { Amount to space between letters }
3135 crBackColor: TColorRef; { Background color }
3136 lid: LCID; { Locale ID }
3137 dwReserved: DWORD; { Reserved. Must be 0 }
3138 sStyle: Smallint; { Style handle }
3139 wKerning: Word; { Twip size above which to kern char pair }
3140 bUnderlineType: Byte; { Underline type }
3141 bAnimation: Byte; { Animated text like marching ants }
3142 bRevAuthor: Byte; { Revision author index }
3143 bReserved1: Byte;
3144 end;
3145 TCharFormat2 = TCharFormat2A;
3147 TParaFormat2 = packed record
3148 cbSize: UINT;
3149 dwMask: DWORD;
3150 wNumbering: Word;
3151 wReserved: Word;
3152 dxStartIndent: Longint;
3153 dxRightIndent: Longint;
3154 dxOffset: Longint;
3155 wAlignment: Word;
3156 cTabCount: Smallint;
3157 rgxTabs: array [0..MAX_TAB_STOPS - 1] of Longint;
3158 dySpaceBefore: Longint; { Vertical spacing before para }
3159 dySpaceAfter: Longint; { Vertical spacing after para }
3160 dyLineSpacing: Longint; { Line spacing depending on Rule }
3161 sStyle: Smallint; { Style handle }
3162 bLineSpacingRule: Byte; { Rule for line spacing (see tom.doc) }
3163 bCRC: Byte; { Reserved for CRC for rapid searching }
3164 wShadingWeight: Word; { Shading in hundredths of a per cent }
3165 wShadingStyle: Word; { Nibble 0: style, 1: cfpat, 2: cbpat }
3166 wNumberingStart: Word; { Starting value for numbering }
3167 wNumberingStyle: Word; { Alignment, roman/arabic, (), ), ., etc. }
3168 wNumberingTab: Word; { Space bet 1st indent and 1st-line text }
3169 wBorderSpace: Word; { Space between border and text (twips) }
3170 wBorderWidth: Word; { Border pen width (twips) }
3171 wBorders: Word; { Byte 0: bits specify which borders }
3172 { Nibble 2: border style, 3: color index }
3173 end;
3175 TGetTextLengthEx = packed record
3176 flags: DWORD; { flags (see GTL_XXX defines) }
3177 codepage: UINT; { code page for translation (CP_ACP for default,
3178 1200 for Unicode }
3179 end;
3181 const
3182 PFM_SPACEBEFORE = $00000040;
3183 PFM_SPACEAFTER = $00000080;
3184 PFM_LINESPACING = $00000100;
3185 PFM_STYLE = $00000400;
3186 PFM_BORDER = $00000800; { (*) }
3187 PFM_SHADING = $00001000; { (*) }
3188 PFM_NUMBERINGSTYLE = $00002000; { (*) }
3189 PFM_NUMBERINGTAB = $00004000; { (*) }
3190 PFM_NUMBERINGSTART = $00008000; { (*) }
3192 PFM_RTLPARA = $00010000;
3193 PFM_KEEP = $00020000; { (*) }
3194 PFM_KEEPNEXT = $00040000; { (*) }
3195 PFM_PAGEBREAKBEFORE = $00080000; { (*) }
3196 PFM_NOLINENUMBER = $00100000; { (*) }
3197 PFM_NOWIDOWCONTROL = $00200000; { (*) }
3198 PFM_DONOTHYPHEN = $00400000; { (*) }
3199 PFM_SIDEBYSIDE = $00800000; { (*) }
3201 PFM_TABLE = $c0000000; { (*) }
3202 EM_REDO = WM_USER + 84;
3203 EM_AUTOURLDETECT = WM_USER + 91;
3204 EM_GETAUTOURLDETECT = WM_USER + 92;
3205 CFM_UNDERLINETYPE = $00800000; { (*) }
3206 CFM_HIDDEN = $0100; { (*) }
3207 CFM_BACKCOLOR = $04000000;
3208 CFE_AUTOBACKCOLOR = CFM_BACKCOLOR;
3209 GTL_USECRLF = 1; { compute answer using CRLFs for paragraphs }
3210 GTL_PRECISE = 2; { compute a precise answer }
3211 GTL_CLOSE = 4; { fast computation of a "close" answer }
3212 GTL_NUMCHARS = 8; { return the number of characters }
3213 GTL_NUMBYTES = 16; { return the number of _bytes_ }
3214 EM_GETTEXTLENGTHEX = WM_USER + 95;
3215 EM_SETLANGOPTIONS = WM_USER + 120;
3216 EM_GETLANGOPTIONS = WM_USER + 121;
3218 EM_SETEDITSTYLE = $400 + 204;
3219 EM_GETEDITSTYLE = $400 + 205;
3221 SES_EMULATESYSEDIT = 1;
3222 SES_BEEPONMAXTEXT = 2;
3223 SES_EXTENDBACKCOLOR = 4;
3224 SES_MAPCPS = 8;
3225 SES_EMULATE10 = 16;
3226 SES_USECRLF = 32;
3227 SES_USEAIMM = 64;
3228 SES_NOIME = 128;
3229 SES_ALLOWBEEPS = 256;
3230 SES_UPPERCASE = 512;
3231 SES_LOWERCASE = 1024;
3232 SES_NOINPUTSEQUENCECHK = 2048;
3233 SES_BIDI = 4096;
3234 SES_SCROLLONKILLFOCUS = 8192;
3235 SES_XLTCRCRLFTOCR = 16384;
3237 //[CONTROLS]
3239 type
3240 {++}(*TControl = class;*){--}
3241 PControl = {-}^{+}TControl;
3242 {* Type of pointer to TControl visual object. All
3243 |<a href="kol_pas.htm#visual_objects_constructors">
3244 constructing functions
3245 |</a>
3246 New[ControlName] are returning
3247 pointer of this type. Do not forget about some difference
3248 of using objects from using classes. Identifier Self for
3249 methods of object is not of pointer type, and to pass
3250 pointer to Self, it is necessary to pass @Self instead.
3251 At the same time, to use pointer to object in 'WITH' operator,
3252 it is necessary to apply suffix '^' to pointer to get know
3253 to compiler, what do You want. }
3255 //[TWindowFunc TYPE]
3256 TWindowFunc = function( Sender: PControl; var Msg: TMsg; var Rslt: Integer )
3257 : Boolean;
3258 {* Event type to define custom extended message handlers (as pointers to
3259 procedure entry points). Such handlers are usually defined like add-ons,
3260 extending behaviour of certain controls and attached using AttachProc
3261 method of TControl. If the handler detects, that it is necessary to stop
3262 further message processing, it should return True. }
3265 //[Mouse TYPES]
3266 TMouseButton = ( mbNone, mbLeft, mbRight, mbMiddle );
3267 {* Available mouse buttons. mbNone is useful to get know, that
3268 there were no mouse buttons pressed. }
3270 TMouseEventData = packed Record
3271 {* Record to pass it to mouse handling routines, assigned to OnMouseXXXX
3272 events. }
3273 Button: TMouseButton;
3274 StopHandling: Boolean; // Set it to True in OnMouseXXXX event handler to
3275 // stop further processing
3276 R1, R2: Byte; // Not used
3277 Shift : DWORD; // HiWord( Shift ) = zDelta in WM_MOUSEWHEEL
3278 X, Y : SmallInt;
3279 end;
3281 TOnMouse = procedure( Sender: PControl; var Mouse: TMouseEventData ) of object;
3282 {* Common mouse handling event type. }
3284 //[Key TYPES]
3285 TOnKey = procedure( Sender: PControl; var Key: Longint; Shift: DWORD ) of object;
3286 {* Key events. Shift is a combination of flags MK_SHIFT, MK_CONTROL, MK_ALT.
3287 (See GetShiftState funtion). }
3289 TOnChar = procedure( Sender: PControl; var Key: Char; Shift: DWORD ) of object;
3290 {* Char event. Shift is a combination of flags MK_SHIFT, MK_CONTROL, MK_ALT. }
3292 TTabKey = ( tkTab, tkLeftRight, tkUpDown, tkPageUpPageDn );
3293 {* Available tabulating key groups. }
3294 TTabKeys = Set of TTabKey;
3295 {* Set of tabulating key groups, allowed to be used in with a control
3296 (are installed by TControl.LookTabKey property). }
3298 //[Event TYPES]
3299 TOnMessage = function( var Msg: TMsg; var Rslt: Integer ): Boolean of object;
3300 {* Event type for events, which allows to extend behaviour of windowed controls
3301 descendants using add-ons. }
3303 TOnEventAccept = procedure( Sender: PObj; var Accept: Boolean ) of object;
3304 {* Event type for OnClose event. }
3305 TCloseQueryReason = ( qClose, qShutdown, qLogoff );
3306 {* Request reason type to call OnClose and OnQueryEndSession. }
3307 TWindowState = ( wsNormal, wsMinimized, wsMaximized );
3308 {* Avalable states of TControl's window object. }
3310 TOnSplit = function( Sender: PControl; NewSize1, NewSize2: Integer ): Boolean of object;
3311 {* Event type for OnSplit event handler, designed specially for splitter
3312 control. Event handler must return True to accept new size of previous
3313 (to splitter) control and new size of the rest of client area of parent. }
3315 TOnTVBeginDrag = procedure( Sender: PControl; Item: THandle ) of object;
3316 {* Event type for OnTVBeginDrag event (defined for tree view control). }
3317 TOnTVBeginEdit = function( Sender: PControl; Item: THandle ): Boolean of object;
3318 {* Event type for OnTVBeginEdit event (for tree view control). }
3319 TOnTVEndEdit = function( Sender: PControl; Item: THandle; const NewTxt: String )
3320 : Boolean of object;
3321 {* Event type for TOnTVEndEdit event. }
3322 TOnTVExpanding = function( Sender: PControl; Item: THandle; Expand: Boolean )
3323 : Boolean of object;
3324 {* Event type for TOnTVExpanding event. }
3325 TOnTVExpanded = procedure( Sender: PControl; Item: THandle; Expand: Boolean )
3326 of object;
3327 {* Event type for OnTVExpanded event. }
3328 TOnTVDelete = procedure( Sender: PControl; Item: THandle ) of object;
3329 {* Event type for OnTVDelete event. }
3331 //--------- by Sergey Shisminzev:
3332 TOnTVSelChanging = function(Sender: PControl; oldItem, newItem: THandle): Boolean //~ss
3333 of object;
3334 {* When the handler returns False, selection is not changed. }
3335 //-------------------------------
3336 TOnDrag = function( Sender: PControl; ScrX, ScrY: Integer; var CursorShape: Integer;
3337 var Stop: Boolean ): Boolean of object;
3338 {* Event, called during dragging operation (it is initiated
3339 with method Drag, where callback function of type TOnDrag is
3340 passed as a parameter). Callback function receives Stop parameter True,
3341 when operation is finishing. Otherwise, it can set it to True to force
3342 finishing the operation (in such case, returning False means cancelling
3343 drag operation, True - successful drag and in this last case callback is
3344 no more called). During the operation, when input Stop value is False,
3345 callback function can control Cursor shape, and return True, if the operation
3346 can be finished successfully at the given ScrX, ScrY position.
3347 ScrX, ScrY are screen coordinates of the mouse cursor. }
3349 //[Create Window STRUCTURES]
3350 TCreateParams = packed record
3351 {* Record to pass it through CreateSubClass method. }
3352 Caption: PChar;
3353 Style: cardinal;
3354 ExStyle: cardinal;
3355 X, Y: Integer;
3356 Width, Height: Integer;
3357 WndParent: HWnd;
3358 Param: Pointer;
3359 WindowClass: TWndClass;
3360 WinClassName: array[0..63] of Char;
3361 end;
3363 TCreateWndParams = packed Record
3364 ExStyle: DWORD;
3365 WinClassName: PChar;
3366 Caption: PChar;
3367 Style: DWORD;
3368 X, Y, Width, Height: Integer;
3369 WndParent: HWnd;
3370 Menu: HMenu;
3371 Inst: THandle;
3372 Param: Pointer;
3373 WinClsNamBuf: array[ 0..63 ] of Char;
3374 WindowClass: TWndClass;
3375 end;
3378 //[COMMAND ACTIONS TYPE FOR DIFFERENT CONTROLS]
3379 PCommandActions = ^TCommandActions;
3380 TCommandActions = packed Record
3381 aClear: procedure( Sender: PControl );
3382 aAddText: procedure( Sender: PControl; const S: String );
3383 aClick, aEnter, aLeave: WORD; aChange: SmallInt; aSelChange: SmallInt;
3384 aGetCount, aSetCount, aGetItemLength, aGetItemText, aSetItemText,
3385 aGetItemData, aSetItemData: WORD;
3386 aAddItem, aDeleteItem, aInsertItem: WORD;
3387 aFindItem, aFindPartial: WORD;
3388 aItem2Pos, aPos2Item: BYTE;
3389 aGetSelCount, aGetSelected, aGetSelRange, aExGetSelRange, aGetCurrent,
3390 aSetSelected, aSetCurrent, aSetSelRange, aExSetSelRange,
3391 aGetSelection, aReplaceSel: WORD;
3392 aTextAlignLeft, aTextAlignRight, aTextAlignCenter: WORD;
3393 aTextAlignMask: Byte;
3394 aVertAlignCenter, aVertAlignTop, aVertAlignBottom: Byte;
3395 aDir, aSetLimit: Word; aSetImgList: Word;
3396 aAutoSzX, aAutoSzY: Word;
3397 aSetBkColor: Word;
3398 aItem2XY: Word;
3399 end;
3401 //[Align TYPES]
3402 TTextAlign = ( taLeft, taRight, taCenter );
3403 {* Text alignments available. }
3404 TRichTextAlign = ( raLeft, raRight, raCenter,
3405 // all other are only set but can not be displayed:
3406 raJustify, // displayed like raLeft (though stored normally)
3407 raInterLetter, raScaled, raGlyphs, raSnapGrid );
3408 {* Text alignment styles, available for RichEdit control. }
3409 TVerticalAlign = ( vaCenter, vaTop, vaBottom );
3410 {* Vertical alignments available. }
3411 TControlAlign = ( caNone, caLeft, caTop, caRight, caBottom, caClient );
3412 {* Control alignments available. }
3414 //[BitBtn TYPES]
3415 TBitBtnOption = ( bboImageList,
3416 bboNoBorder,
3417 bboNoCaption,
3418 bboFixed );
3419 {* Options available for NewBitBtn. }
3420 TBitBtnOptions = set of TBitBtnOption;
3421 {* Set of options, available for NewBitBtn. }
3422 TGlyphLayout = ( glyphLeft, glyphTop, glyphRight, glyphBottom, glyphOver );
3423 {* Layout of glyph (for NewBitBtn). Layout glyphOver means that text is
3424 drawn over glyph. }
3425 TOnBitBtnDraw = function( Sender: PControl; BtnState: Integer ): Boolean of object;
3426 {* Event type for TControl.OnBitBtnDraw event (which is called just before
3427 drawing the BitBtn). If handler returns True, there are no drawing occure.
3428 BtnState, passed to a handler, determines current button state and can
3429 be following: 0 - not pressed, 1 - pressed, 2 - disabled, 3 - focused.
3430 Value 4 is reserved for highlight state (then mouse is over it), but
3431 highlighting is provided only if property Flat is set to True (or one
3432 of events OnMouseEnter / OnMouseLeave is assigned to something). }
3434 //[ListView TYPES]
3435 TListViewStyle = ( lvsIcon, lvsSmallIcon, lvsList, lvsDetail, lvsDetailNoHeader );
3436 {* Styles of view for ListView control (see NewListVew). }
3438 TListViewItemStates = ( lvisFocus, lvisSelect, lvisBlend, lvisHighlight );
3439 TListViewItemState = Set of TListViewItemStates;
3440 TListViewOption = (
3441 lvoIconLeft, // in lvsIcon, lvsSmallIcon plce icon left from text (rather then top)
3442 lvoAutoArrange, // keep icons auto arranged in lvsIcon and lvsSmallIcon view
3443 lvoButton, // icons look like buttons in lvsIcon view
3444 lvoEditLabel, // allows edit labels inplace (first column #0 text)
3445 lvoNoLabelWrap, // item text on a single line in lvsIcon view (by default, item text may wrap in lvsIcon view).
3446 lvoNoScroll, // obvious
3447 lvoNoSortHeader, // click on header button does not lead to sort items
3448 lvoHideSel, // hide selection when not in focus
3449 lvoMultiselect, // allow to select multiple items
3450 lvoSortAscending,
3451 lvoSortDescending,
3452 // extended styles (not documented in my Win32.hlp :( , got from VCL source:
3453 lvoGridLines,
3454 lvoSubItemImages,
3455 lvoCheckBoxes,
3456 lvoTrackSelect,
3457 lvoHeaderDragDrop,
3458 lvoRowSelect,
3459 lvoOneClickActivate,
3460 lvoTwoClickActivate,
3461 lvoFlatsb,
3462 lvoRegional,
3463 lvoInfoTip,
3464 lvoUnderlineHot,
3465 lvoMultiWorkares,
3466 // virtual list view style:
3467 lvoOwnerData,
3468 // custom draw style:
3469 lvoOwnerDrawFixed
3471 TListViewOptions = Set of TListViewOption;
3473 TOnEditLVItem = function( Sender: PControl; Idx, Col: Integer; NewText: PChar ): Boolean
3474 of object;
3475 {* Event type for OnEndEditLVItem. Return True in handler to accept new text value. }
3476 TOnDeleteLVItem = procedure( Sender: PControl; Idx: Integer ) of object;
3477 {* Event type for OnDeleteLVItem event. }
3478 TOnLVData = procedure( Sender: PControl; Idx, SubItem: Integer;
3479 var Txt: String; var ImgIdx: Integer; var State: DWORD;
3480 var Store: Boolean ) of object;
3481 {* Event type for OnLVData event. Used to provide virtual list view control
3482 (i.e. having lvoOwnerData style) with actual data on request. Use parameter
3483 Store as a flag if control should store obtained data by itself or not. }
3484 {$IFNDEF _D2}
3485 {$IFNDEF _FPC}
3486 TOnLVDataW = procedure( Sender: PControl; Idx, SubItem: Integer;
3487 var Txt: WideString; var ImgIdx: Integer; var State: DWORD;
3488 var Store: Boolean ) of object;
3489 {* Event type for OnLVDataW event (the same as OnLVData, but for unicode verion
3490 of the control OnLVDataW allows to return WideString text in the event
3491 handler). Used to provide virtual list view control
3492 (i.e. having lvoOwnerData style) with actual data on request. Use parameter
3493 Store as a flag if control should store obtained data by itself or not. }
3494 {$ENDIF _FPC}
3495 {$ENDIF _D2}
3496 TOnCompareLVItems = function( Sender: PControl; Idx1, Idx2: Integer ): Integer
3497 of object;
3498 {* Event type to compare two items of the list view (while sorting it). }
3499 TOnLVColumnClick = procedure( Sender: PControl; Idx: Integer ) of object;
3500 {* Event type for OnColumnClick event. }
3501 TOnLVStateChange = procedure( Sender: PControl; IdxFrom, IdxTo: Integer; OldState, NewState: DWORD )
3502 of object;
3503 {* Event type for OnLVStateChange event, called in responce to select/unselect
3504 a single item or items range in list view control). }
3505 TOnLVDelete = procedure( Sender: PControl; Idx: Integer ) of object;
3506 {* Event type for OnLVDelete event, called when an item is been deleting. }
3508 TDrawActions = ( odaEntire, odaFocus, odaSelect );
3509 TDrawAction = Set of TDrawActions;
3510 TDrawStates = ( odsSelected, odsGrayed, odsDisabled, odsChecked, odsFocused,
3511 odsDefault, odsHotlist, odsInactive,
3512 odsNoAccel, odsNoFocusRect,
3513 ods400reserved, ods800reserved,
3514 odsComboboxEdit,
3515 // specific for common controls:
3516 odsMarked, odsIndeterminate );
3517 {* Possible draw states.
3518 |<br>odsSelected - The menu item's status is selected.
3519 |<br>odsGrayed - The item is to be grayed. This bit is used only in a menu.
3520 |<br>odsDisabled - The item is to be drawn as disabled.
3521 |<br>odsChecked - The menu item is to be checked. This bit is used only in
3522 a menu.
3523 |<br>odsFocused - The item has the keyboard focus.
3524 |<br>odsDefault - The item is the default item.
3525 |<br>odsHotList - <b>Windows 98, Windows 2000:</b> The item is being
3526 hot-tracked, that is, the item will be highlighted when
3527 the mouse is on the item.
3528 |<br>odsInactive - <b>Windows 98, Windows 2000:</b> The item is inactive
3529 and the window associated with the menu is inactive.
3530 |<br>odsNoAccel - <b>Windows 2000:</b> The control is drawn without the
3531 keyboard accelerator cues.
3532 |<br>odsNoFocusRect - <b>Windows 2000:</b> The control is drawn without
3533 focus indicator cues.
3534 |<br>odsComboboxEdit - The drawing takes place in the selection field
3535 (edit control) of an owner-drawn combo box.
3536 |<br>odsMarked - for Common controls only. The item is marked. The meaning
3537 of this is up to the implementation.
3538 |<br>odsIndeterminate - for Common Controls only. The item is in an
3539 indeterminate state. }
3540 TDrawState = Set of TDrawStates;
3541 {* Set of possible draw states. }
3542 TOnDrawItem = function( Sender: PObj; DC: HDC; const Rect: TRect; ItemIdx: Integer;
3543 DrawAction: TDrawAction; ItemState: TDrawState ): Boolean of object;
3544 {* Event type for OnDrawItem event (applied to list box, combo box, list view). }
3545 TOnMeasureItem = function( Sender: PObj; Idx: Integer ): Integer of object;
3546 {* Event type for OnMeasureItem event. The event handler must return height of list box
3547 item as a result. }
3548 TGetLVItemPart = ( lvipBounds, lvipIcon, lvipLabel, lvupIconAndLabel );
3549 {* }
3550 TWherePosLVItem = ( lvwpOnIcon, lvwpOnLabel, lvwpOnStateIcon, lvwpOnColumn,
3551 lvwpOnItem );
3552 {* }
3554 TOnLVCustomDraw = function( Sender: PControl; DC: HDC; Stage: DWORD;
3555 ItemIdx, SubItemIdx: Integer; const Rect: TRect;
3556 ItemState: TDrawState; var TextColor, BackColor: TColor )
3557 : DWORD of object;
3558 {* Event type for OnLVCustomDraw event. }
3560 //[Paint TYPES]
3561 TOnPaint = procedure( Sender: PControl; DC: HDC ) of object;
3563 TGradientStyle = ( gsVertical, gsHorizontal, gsRectangle, gsElliptic, gsRombic );
3564 {* Gradient fill styles. See also TGradientLayout. }
3565 TGradientLayout = ( glTopLeft, glTop, glTopRight,
3566 glLeft, glCenter, glRight,
3567 glBottomLeft, glBottom, glBottomRight );
3568 {* Position of starting line / point for gradient filling. Depending on
3569 TGradientStyle, means either position of first line of first rectangle
3570 (ellipse) to be expanded in a loop to fit entire gradient panel area. }
3572 //[Edit TYPES]
3573 TEditOption = ( eoNoHScroll, eoNoVScroll, eoLowercase, eoMultiline,
3574 eoNoHideSel, eoOemConvert, eoPassword, eoReadonly,
3575 eoUpperCase, eoWantReturn, eoWantTab, eoNumber );
3576 {* Available edit options.
3577 |<br> Please note, that eoWantTab option just removes TAB key from a list
3578 of keys available to tabulate from the edit control. To provide insertion
3579 of tabulating key, do so in TControl.OnChar event handler. Sorry for
3580 inconvenience, but this is because such behaviour is not must in all cases.
3581 See also TControl.EditTabChar property. }
3582 TEditOptions = Set of TEditOption;
3583 {* Set of available edit options. }
3585 TRichFmtArea = ( raSelection, raWord, raAll );
3586 {* Characters formatting area for RichEdit. }
3587 TRETextFormat = ( reRTF, reText, rePlainRTF, reRTFNoObjs, rePlainRTFNoObjs,
3588 reTextized );
3589 {* Available formats for transfer RichEdit text using property
3590 TControl.RE_Text.
3591 |<pre>
3592 reRTF - normal rich text (no transformations)
3593 reText - plain text only (without OLE objects)
3594 reTextized - plain text with text representation of OLE objects
3595 rePlainRTF - reRTF without language-specific keywords
3596 reRTFNoObjs - reRTF without OLE objects
3597 rePlainRTFNoObjs - rePlainRTF without OLE objects
3598 |</pre> }
3599 TRichUnderline = ( ruSingle, ruWord, ruDouble, ruDotted,
3600 //all other - only for RichEditv3.0:
3601 ruDash, ruDashDot, ruDashDotDot, ruWave, ruThick, ruHairLine );
3602 {* Rich text exteded underline styles (available only for RichEdit v2.0,
3603 and even for RichEdit v2.0 additional styles can not displayed - but
3604 ruDotted under Windows2000 is working). }
3605 TRichTextSizes = ( rtsNoUseCRLF, rtsNoPrecise, rtsClose, rtsBytes );
3606 {* Options to calculate size of rich text. Available only for RichEdit2.0
3607 or higher. }
3608 TRichTextSize = set of TRichTextSizes;
3609 {* Set of all available optioins to calculate rich text size using
3610 property TControl.RE_TextSize[ options ]. }
3611 TRichNumbering = ( rnNone, rnBullets, rnArabic, rnLLetter, rnULetter,
3612 rnLRoman, rnURoman );
3613 {* Advanced numbering styles for paragraph (RichEdit).
3614 |<pre>
3615 rnNone - no numbering
3616 rnBullets - bullets only
3617 rnArabic - 1, 2, 3, 4, ...
3618 rnLLetter - a, b, c, d, ...
3619 rnULetter - A, B, C, D, ...
3620 rnLRoman - i, ii, iii, iv, ...
3621 rnURoman - I, II, III, IV, ...
3622 rnNoNumber - do not show any numbers (but numbering is taking place).
3623 |</pre> }
3624 TRichNumBrackets = ( rnbRight, rnbBoth, rnbPeriod, rnbPlain, rnbNoNumber );
3625 {* Brackets around number:
3626 |<pre>
3627 rnbRight - 1) 2) 3) - this is default !
3628 rnbBoth - (1) (2) (3)
3629 rnbPeriod - 1. 2. 3.
3630 rnbPlain - 1 2 3
3631 |</pre> }
3632 TBorderEdge = (beLeft, beTop, beRight, beBottom);
3633 {* Borders of rectangle. }
3635 TCharFormat = TCharFormat2;
3636 TParaFormat = TParaFormat2;
3638 TOnTestMouseOver = function( Sender: PControl ): Boolean of object;
3639 {* Event type for TControl.OnTestMouseOver event. The handler should
3640 return True, if it dectects, that mouse is over control. }
3642 TEdgeStyle = ( esRaised, esLowered, esNone );
3643 {* Edge styles (for panel - see NewPanel). }
3645 //[List TYPES]
3646 TListOption = ( loNoHideScroll, loNoExtendSel, loMultiColumn, loMultiSelect,
3647 loNoIntegralHeight, loNoSel, loSort, loTabstops,
3648 loNoStrings, loNoData, loOwnerDrawFixed, loOwnerDrawVariable );
3649 {* Options for ListBox (see NewListbox). }
3650 TListOptions = Set of TListOption;
3651 {* Set of available options for Listbox. }
3653 TComboOption = ( coReadOnly, coNoHScroll, coAlwaysVScroll, coLowerCase,
3654 coNoIntegralHeight, coOemConvert, coSort, coUpperCase,
3655 coOwnerDrawFixed, coOwnerDrawVariable, coSimple );
3656 {* Options for combobox. }
3657 TComboOptions = Set of TComboOption;
3658 {* Set of options available for combobox. }
3660 //[Progress TYPES]
3661 TProgressbarOption = ( pboVertical, pboSmooth );
3662 {* Options for progress bar. }
3663 TProgressbarOptions = set of TProgressbarOption;
3664 {* Set of options available for progress bar. }
3666 //[TreeView TYPES]
3667 TTreeViewOption = ( tvoNoLines, tvoLinesRoot, tvoNoButtons, tvoEditLabels, tvoHideSel,
3668 tvoDragDrop, tvoNoTooltips, tvoCheckBoxes, tvoTrackSelect,
3669 tvoSingleExpand, tvoInfoTip, tvoFullRowSelect, tvoNoScroll,
3670 tvoNonEvenHeight );
3671 {* Tree view options. }
3672 TTreeViewOptions = set of TTreeViewOption;
3673 {* Set of tree view options. }
3675 //[TabControl TYPES]
3676 TTabControlOption = ( tcoButtons, tcoFixedWidth, tcoFocusTabs,
3677 tcoIconLeft, tcoLabelLeft,
3678 tcoMultiline, tcoMultiselect, tcoFitRows, tcoScrollOpposite,
3679 tcoBottom, tcoVertical, tcoFlat, tcoHotTrack, tcoBorder,
3680 tcoOwnerDrawFixed );
3681 {* Options, available for TabControl. }
3682 TTabControlOptions = set of TTabControlOption;
3683 {* Set of options, available for TAbControl during its creation (by
3684 NewTabControl function). }
3686 //[Toolbar TYPES]
3687 TToolbarOption = ( tboTextRight, tboTextBottom, tboFlat, tboTransparent,
3688 tboWrapable, tboNoDivider, tbo3DBorder );
3689 {* Toolbar options. When tboFlat is set and toolbar is placed onto panel,
3690 set its property Transparent to TRUE to provide its correct view. }
3691 TToolbarOptions = Set of TToolbarOption;
3692 {* Set of toolbar options. }
3693 TOnToolbarButtonClick = procedure( Sender: PControl; BtnID: Integer ) of object;
3694 {* Special event type to handle separate toolbar buttons click events. }
3696 TDateTimePickerOption = ( dtpoTime, dtpoDateLong, dtpoUpDown, dtpoRightAlign,
3697 dtpoShowNone, dtpoParseInput );
3698 {* }
3699 TDateTimePickerOptions = set of TDateTimePickerOption;
3700 {* }
3701 TDTParseInputEvent = procedure(Sender: PControl; const UserString: string;
3702 var DateAndTime: TDateTime; var AllowChange: Boolean) of object;
3703 {* }
3704 TDateTimeRange = array[ 0..1 ] of TDateTime;
3705 {* }
3706 TDateTimePickerColor = ( dtpcBackground, dtpcMonthBk, dtpcText, dtpcTitleBk,
3707 dtpcTitleText, dtpcTrailingText );
3709 //[TOnDropFiles TYPE]
3710 TOnDropFiles = procedure( Sender: PControl; const FileList: String; const Pt: TPoint ) of object;
3711 {* An event type for OnDropFiles event. When the event is occur, FileList
3712 parameter contains a list of files dropped. File names in a list are
3713 separated with #13 character. This allows You to assign it to TStrList
3714 object using its property Text (for example):
3715 ! procedure TSomeObject.DropFiles( Sender: PControl; const FileList: String;
3716 ! const Pt: TPoint ); )
3717 ! var FList: PStrList;
3718 ! I: Integer;
3719 ! begin
3720 ! FList := NewStrList;
3721 ! FList.Text := FileList;
3722 ! for I := 0 to FList.Count-1 do
3723 ! begin
3724 ! // do something with FList.Items[ I ]
3725 ! end;
3726 ! FList.Free;
3727 ! end; }
3729 //[Scroll TYPES]
3730 TScrollerBar = ( sbHorizontal, sbVertical );
3731 TScrollerBars = set of TScrollerBar;
3733 TOnScroll = procedure( Sender: PControl; Bar: TScrollerBar; ScrollCmd: DWORD;
3734 ThumbPos: DWORD ) of object;
3736 //[TOnHelp EVENT TYPE]
3737 TOnHelp = procedure( var Sender: PControl; var Context: Integer; var Popup: Boolean )
3738 of object;
3740 //[ScrollBar TYPES]
3741 TOnSBBeforeScroll =
3742 procedure(
3743 Sender: PControl; OldPos, NewPos: Integer; Cmd: Word;
3744 var AllowChange: Boolean) of object;
3745 TOnSBScroll = procedure(Sender: PControl; Cmd: Word) of object;
3748 {$IFDEF USE_MHTOOLTIP}
3749 {$DEFINE pre_interface}
3750 {$I KOLMHToolTip}
3751 {$UNDEF pre_interface}
3752 {$ENDIF}
3754 { ----------------------------------------------------------------------
3756 TControl - object to implement any visual control
3758 ----------------------------------------------------------------------- }
3759 //[TControl DEFINITION]
3760 TControl = object( TObj )
3761 protected
3762 fSBMinMax: TPoint;
3763 fSBPageSize: Integer;
3764 fSBPosition: Integer;
3765 procedure SetSBMax(Value: Longint);
3766 procedure SetSBMin(Value: Longint);
3767 procedure SetSBPageSize(Value: Integer);
3768 procedure SetSBPosition(Value: Integer);
3769 procedure SetSBMinMax(const Value: TPoint);
3771 function GetDate: TDateTime;
3772 function GetTime: TDateTime;
3773 procedure SetDate(const Value: TDateTime);
3774 procedure SetTime(const Value: TDateTime);
3775 {*! TControl is the basic visual object of KOL. And now, all visual
3776 objects have the same type PControl, differing only in "constructor",
3777 which during creating of object adjusts it so it can play role of
3778 desired control. Idea of incapsulating of all visual objects having
3779 the most common set of properties, is belonging to Vladimir Kladov,
3780 (C) 2000.
3781 |<br>&nbsp;&nbsp;&nbsp;<b> Since all visual objects are represented
3782 in KOL by this single object type, not all methods, properties and
3783 events defined in TControl, are applicable to different visual objects.
3784 See also notes about certain control kinds, located together with its
3785 |<a href="kol_pas.htm#visual_objects_constructors">
3786 |constructing functions definitions</a></b>. }
3787 protected
3788 function GetHelpPath: String;
3789 procedure SetHelpPath(const Value: String);
3790 procedure SetOnQueryEndSession(const Value: TOnEventAccept);
3791 procedure SetOnMinMaxRestore(const Index: Integer; const Value: TOnEvent);
3792 procedure SetConstraint(const Index, Value: Integer);
3793 {$IFDEF F_P}
3794 function GetOnMinMaxRestore(const Index: Integer): TOnEvent;
3795 function GetConstraint(const Index: Integer): Integer;
3796 {$ENDIF F_P}
3797 procedure SetOnScroll(const Value: TOnScroll);
3798 function GetLVColalign(Idx: Integer): TTextAlign;
3799 procedure SetLVColalign(Idx: Integer; const Value: TTextAlign);
3801 procedure SetParent( Value: PControl );
3802 function GetLeft: Integer;
3803 procedure SetLeft( Value: Integer );
3804 function GetTop: Integer;
3805 procedure SetTop( Value: Integer );
3806 function GetWidth: Integer;
3807 procedure SetWidth( Value: Integer );
3808 function GetHeight: Integer;
3809 procedure SetHeight( Value: Integer );
3811 function GetPosition: TPoint;
3812 procedure Set_Position( Value: TPoint );
3814 function GetMembers(Idx: Integer): PControl;
3815 function GetFont: PGraphicTool;
3816 procedure FontChanged( Sender: PGraphicTool );
3817 function GetBrush: PGraphicTool;
3818 procedure BrushChanged( Sender: PGraphicTool );
3819 function GetClientHeight: Integer;
3820 function GetClientWidth: Integer;
3821 procedure SetClientHeight(const Value: Integer);
3822 procedure SetClientWidth(const Value: Integer);
3823 function GetHasBorder: Boolean;
3824 procedure SetHasBorder(const Value: Boolean);
3826 function GetHasCaption: Boolean;
3827 procedure SetHasCaption(const Value: Boolean);
3829 function GetCanResize: Boolean;
3830 procedure SetCanResize( const Value: Boolean );
3832 function GetStayOnTop: Boolean;
3833 procedure SetStayOnTop(const Value: Boolean);
3834 function GetChecked: Boolean;
3835 procedure Set_Checked(const Value: Boolean);
3837 function GetSelStart: Integer;
3838 procedure SetSelStart(const Value: Integer);
3839 function GetSelLength: Integer;
3840 procedure SetSelLength(const Value: Integer);
3842 function GetItems(Idx: Integer): String;
3843 procedure SetItems(Idx: Integer; const Value: String);
3845 function GetItemsCount: Integer;
3846 function GetItemSelected(ItemIdx: Integer): Boolean;
3847 procedure SetItemSelected(ItemIdx: Integer; const Value: Boolean);
3849 procedure SetCtl3D(const Value: Boolean);
3850 function GetCurIndex: Integer;
3851 procedure SetCurIndex(const Value: Integer);
3852 function GetTextAlign: TTextAlign;
3853 function GetVerticalAlign: TVerticalAlign;
3854 procedure SetTextAlign(const Value: TTextAlign);
3855 procedure SetVerticalAlign(const Value: TVerticalAlign);
3857 function GetCanvas: PCanvas;
3858 function Dc2Canvas( Sender: PCanvas ): HDC;
3859 procedure SetShadowDeep(const Value: Integer);
3860 procedure SetDoubleBuffered(const Value: Boolean);
3862 procedure SetStatusText(Index: Integer; Value: PChar);
3863 function GetStatusText( Index: Integer ): PChar;
3864 function GetStatusPanelX(Idx: Integer): Integer;
3865 procedure SetStatusPanelX(Idx: Integer; const Value: Integer);
3867 procedure SetTransparent(const Value: Boolean);
3868 function GetImgListIdx(const Index: Integer): PImageList;
3870 procedure SetImgListIdx(const Index: Integer; const Value: PImageList);
3871 function GetLVColText(Idx: Integer): String;
3872 procedure SetLVColText(Idx: Integer; const Value: String);
3873 {$IFNDEF _FPC}
3874 {$IFNDEF _D2}
3875 function GetLVColTextW(Idx: Integer): WideString;
3876 procedure SetLVColTextW(Idx: Integer; const Value: WideString);
3877 {$ENDIF _D2}
3878 {$ENDIF _FPC}
3879 function LVGetItemText(Idx, Col: Integer): String;
3880 procedure LVSetItemText(Idx, Col: Integer; const Value: String);
3881 {$IFNDEF _FPC}
3882 {$IFNDEF _D2}
3883 function LVGetItemTextW(Idx, Col: Integer): WideString;
3884 procedure LVSetItemTextW(Idx, Col: Integer; const Value: WideString);
3885 {$ENDIF _D2}
3886 {$ENDIF _FPC}
3887 procedure SetLVOptions(const Value: TListViewOptions);
3888 procedure SetLVStyle(const Value: TListViewStyle);
3889 function GetLVColEx(Idx: Integer; const Index: Integer): Integer;
3890 procedure SetLVColEx(Idx: Integer; const Index: Integer;
3891 const Value: Integer);
3893 function GetChildCount: Integer;
3895 function LVGetItemPos(Idx: Integer): TPoint;
3896 procedure LVSetItemPos(Idx: Integer; const Value: TPoint);
3897 procedure LVSetColorByIdx(const Index: Integer; const Value: TColor);
3898 {$IFDEF F_P}
3899 function LVGetColorByIdx(const Index: Integer): TColor;
3900 {$ENDIF F_P}
3901 function GetIntVal(const Index: Integer): Integer;
3902 procedure SetIntVal(const Index, Value: Integer);
3903 function GetItemVal(Item: Integer; const Index: Integer): Integer;
3904 procedure SetItemVal(Item: Integer; const Index, Value: Integer);
3905 function TBGetButtonVisible(BtnID: Integer): Boolean;
3906 procedure TBSetButtonVisible(BtnID: Integer; const Value: Boolean);
3908 function TBGetBtnStt(BtnID: Integer; const Index: Integer): Boolean;
3909 procedure TBSetBtnStt(BtnID: Integer; const Index: Integer; const Value: Boolean);
3910 function TBGetButtonText(BtnID: Integer): String;
3911 function TBGetButtonRect(BtnID: Integer): TRect;
3913 function TBGetRows: Integer;
3914 procedure TBSetRows(const Value: Integer);
3915 procedure SetProgressColor(const Value: TColor);
3916 function TBGetBtnImgIdx(BtnID: Integer): Integer;
3917 procedure TBSetBtnImgIdx(BtnID: Integer; const Value: Integer);
3919 procedure TBSetButtonText(BtnID: Integer; const Value: String);
3921 function TBGetBtnWidth(BtnID: Integer): Integer;
3922 procedure TBSetBtnWidth(BtnID: Integer; const Value: Integer);
3923 procedure TBSetBtMinMaxWidth(const Idx: Integer; const Value: Integer);
3924 {$IFDEF F_P}
3925 function TBGetBtMinMaxWidth(const Idx: Integer): Integer;
3926 {$ENDIF F_P}
3927 procedure TBFreeTBevents;
3928 procedure Set_Align(const Value: TControlAlign);
3929 function GetSelection: String;
3930 procedure SetSelection(const Value: String);
3931 procedure SetTabOrder(const Value: Integer);
3932 function GetFocused: Boolean;
3933 procedure SetFocused(const Value: Boolean);
3934 function REGetFont: PGraphicTool;
3935 procedure RESetFont(Value: PGraphicTool);
3936 procedure RESetFontEx(const Index: Integer);
3937 function REGetFontEffects(const Index: Integer): Boolean;
3938 function REGetFontMask(const Index: Integer): Boolean;
3939 procedure RESetFontEffect(const Index: Integer; const Value: Boolean);
3940 function REGetFontAttr(const Index: Integer): Integer;
3941 procedure RESetFontAttr(const Index, Value: Integer);
3942 procedure RESetFontAttr1(const Index, Value: Integer);
3943 function REGetFontSizeValid: Boolean;
3944 function REGetCharformat: TCharFormat;
3945 procedure RESetCharFormat(const Value: TCharFormat);
3946 function REReadText(Format: TRETextFormat;
3947 SelectionOnly: Boolean): String;
3948 procedure REWriteText(Format: TRETextFormat; SelectionOnly: Boolean;
3949 const Value: String);
3950 function REGetFontName: String;
3951 procedure RESetFontName(const Value: String);
3952 function REGetParaFmt: TParaFormat;
3953 procedure RESetParaFmt(const Value: TParaFormat);
3954 function REGetNumbering: Boolean;
3955 function REGetParaAttr( const Index: Integer ): Integer;
3956 function REGetParaAttrValid( const Index: Integer ): Boolean;
3957 function REGetTabCount: Integer;
3958 function REGetTabs(Idx: Integer): Integer;
3959 function REGetTextAlign: TRichTextAlign;
3960 procedure RESetNumbering(const Value: Boolean);
3961 procedure RESetParaAttr(const Index, Value: Integer);
3962 procedure RESetTabCount(const Value: Integer);
3963 procedure RESetTabs(Idx: Integer; const Value: Integer);
3964 procedure RESetTextAlign(const Value: TRichTextAlign);
3965 function REGetStartIndentValid: Boolean;
3966 function REGetAutoURLDetect: Boolean;
3967 procedure RESetAutoURLDetect(const Value: Boolean);
3969 function GetMaxTextSize: DWORD;
3970 procedure SetMaxTextSize(const Value: DWORD);
3971 procedure SetOnResize(const Value: TOnEvent);
3973 procedure DoSelChange;
3975 function REGetUnderlineEx: TRichUnderline;
3976 procedure RESetUnderlineEx(const Value: TRichUnderline);
3978 function GetTextSize: Integer;
3979 function REGetTextSize(Units: TRichTextSize): Integer;
3981 function REGetNumStyle: TRichNumbering;
3982 procedure RESetNumStyle(const Value: TRichNumbering);
3983 function REGetNumBrackets: TRichNumBrackets;
3984 procedure RESetNumBrackets(const Value: TRichNumBrackets);
3985 function REGetNumTab: Integer;
3986 procedure RESetNumTab(const Value: Integer);
3987 function REGetNumStart: Integer;
3988 procedure RESetNumStart(const Value: Integer);
3989 function REGetSpacing(const Index: Integer): Integer;
3990 procedure RESetSpacing(const Index, Value: Integer);
3991 function REGetSpacingRule: Integer;
3992 procedure RESetSpacingRule(const Value: Integer);
3993 function REGetLevel: Integer;
3994 function REGetBorder(Side: TBorderEdge; const Index: Integer): Integer;
3995 procedure RESetBorder(Side: TBorderEdge; const Index: Integer;
3996 const Value: Integer);
3997 function REGetParaEffect(const Index: Integer): Boolean;
3998 procedure RESetParaEffect(const Index: Integer; const Value: Boolean);
3999 function REGetOverwite: Boolean;
4000 procedure RESetOverwrite(const Value: Boolean);
4001 procedure RESetOvrDisable(const Value: Boolean);
4002 function REGetTransparent: Boolean;
4003 procedure RESetTransparent(const Value: Boolean);
4004 procedure RESetOnURL(const Index: Integer; const Value: TOnEvent);
4005 {$IFDEF F_P}
4006 function REGetOnURL(const Index: Integer): TOnEvent;
4007 {$ENDIF F_P}
4008 function REGetLangOptions(const Index: Integer): Boolean;
4009 procedure RESetLangOptions(const Index: Integer; const Value: Boolean);
4010 function LVGetItemImgIdx(Idx: Integer): Integer;
4011 procedure LVSetItemImgIdx(Idx: Integer; const Value: Integer);
4012 procedure SetFlat(const Value: Boolean);
4013 procedure SetOnMouseEnter(const Value: TOnEvent);
4014 procedure SetOnMouseLeave(const Value: TOnEvent);
4015 procedure EdSetTransparent(const Value: Boolean);
4016 procedure SetOnTestMouseOver(const Value: TOnTestMouseOver);
4017 function GetPages(Idx: Integer): PControl;
4018 function TCGetItemText(Idx: Integer): String;
4019 procedure TCSetItemText(Idx: Integer; const Value: String);
4020 function TCGetItemImgIDx(Idx: Integer): Integer;
4021 procedure TCSetItemImgIdx(Idx: Integer; const Value: Integer);
4022 function TCGetItemRect(Idx: Integer): TRect;
4023 function TVGetItemIdx(const Index: Integer): THandle;
4024 procedure TVSetItemIdx(const Index: Integer; const Value: THandle);
4025 function TVGetItemNext(Item: THandle; const Index: Integer): THandle;
4026 function TVGetItemRect(Item: THandle; TextOnly: Boolean): TRect;
4027 function TVGetItemVisible(Item: THandle): Boolean;
4028 procedure TVSetITemVisible(Item: THandle; const Value: Boolean);
4029 function TVGetItemStateFlg(Item: THandle; const Index: Integer): Boolean;
4030 procedure TVSetItemStateFlg(Item: THandle; const Index: Integer;
4031 const Value: Boolean);
4032 function TVGetItemImage(Item: THandle; const Index: Integer): Integer;
4033 procedure TVSetItemImage(Item: THandle; const Index: Integer;
4034 const Value: Integer);
4035 function TVGetItemText(Item: THandle): String;
4036 procedure TVSetItemText(Item: THandle; const Value: String);
4037 {$IFNDEF _FPC}
4038 {$IFNDEF _D2}
4039 function TVGetItemTextW(Item: THandle): WideString;
4040 procedure TVSetItemTextW(Item: THandle; const Value: WideString);
4041 {$ENDIF _D2}
4042 {$ENDIF _FPC}
4043 function TV_GetItemHasChildren(Item: THandle): Boolean;
4044 procedure TV_SetItemHasChildren(Item: THandle; const Value: Boolean);
4045 function TV_GetItemChildCount(Item: THandle): Integer;
4046 function TVGetItemData(Item: THandle): Pointer;
4047 procedure TVSetItemData(Item: THandle; const Value: Pointer);
4049 function GetToBeVisible: Boolean;
4051 procedure SetAlphaBlend(const Value: Integer);
4052 procedure SetMaxProgress(const Index, Value: Integer);
4053 procedure SetDroppedWidth(const Value: Integer);
4054 function LVGetItemState(Idx: Integer): TListViewItemState;
4055 procedure LVSetItemState(Idx: Integer; const Value: TListViewItemState);
4056 function LVGetSttImgIdx(Idx: Integer): Integer;
4057 procedure LVSetSttImgIdx(Idx: Integer; const Value: Integer);
4058 function LVGetOvlImgIdx(Idx: Integer): Integer;
4059 procedure LVSetOvlImgIdx(Idx: Integer; const Value: Integer);
4060 function LVGetItemData(Idx: Integer): DWORD;
4061 procedure LVSetItemData(Idx: Integer; const Value: DWORD);
4062 function LVGetItemIndent(Idx: Integer): Integer;
4063 procedure LVSetItemIndent(Idx: Integer; const Value: Integer);
4064 procedure SetOnDeleteAllLVItems(const Value: TOnEvent);
4065 procedure SetOnDeleteLVItem(const Value: TOnDeleteLVItem);
4066 procedure SetOnEditLVItem(const Value: TOnEditLVItem);
4067 procedure SetOnLVData(const Value: TOnLVData);
4068 {$IFNDEF _FPC}
4069 {$IFNDEF _D2}
4070 procedure SetOnLVDataW(const Value: TOnLVDataW);
4071 {$ENDIF _D2}
4072 {$ENDIF _FPC}
4073 procedure SetOnColumnClick(const Value: TOnLVColumnClick);
4074 procedure SetOnDrawItem(const Value: TOnDrawItem);
4075 procedure SetOnMeasureItem(const Value: TOnMeasureItem);
4077 procedure SetItemsCount(const Value: Integer);
4079 function GetItemData(Idx: Integer): DWORD;
4080 procedure SetItemData(Idx: Integer; const Value: DWORD);
4081 function GetLVCurItem: Integer;
4082 procedure SetLVCurItem(const Value: Integer);
4083 procedure SetOnDropFiles(const Value: TOnDropFiles);
4084 procedure SetOnHide(const Value: TOnEvent);
4085 procedure SetOnShow(const Value: TOnEvent);
4086 procedure SetClientMargin(const Index, Value: Integer);
4087 {$IFDEF F_P}
4088 function GetClientMargin(const Index: Integer): Integer;
4089 {$ENDIF F_P}
4090 procedure SetOnPaint(const Value: TOnPaint);
4091 procedure SetOnEraseBkgnd(const Value: TOnPaint);
4092 procedure SetTVRightClickSelect(const Value: Boolean);
4093 procedure SetOnLVStateChange(const Value: TOnLVStateChange);
4094 procedure SetOnLVDelete(const Value: TOnLVDelete);
4095 procedure SetOnMove(const Value: TOnEvent);
4096 procedure SetColor1(const Value: TColor);
4097 procedure SetColor2(const Value: TColor);
4098 procedure SetGradientLayout(const Value: TGradientLayout);
4099 procedure SetGradientStyle(const Value: TGradientStyle);
4100 procedure SetDroppedDown(const Value: Boolean);
4101 function get_ClassName: String;
4102 procedure set_ClassName(const Value: String);
4103 procedure SetClsStyle( Value: DWord );
4105 procedure SetStyle( Value: DWord );
4106 procedure SetExStyle( Value: DWord );
4108 procedure SetCursor( Value: HCursor );
4110 procedure SetIcon( Value: HIcon );
4111 procedure SetMenu( Value: HMenu );
4112 function GetCaption: String;
4113 procedure SetCaption( const Value: String );
4115 procedure SetWindowState( Value: TWindowState );
4116 function GetWindowState: TWindowState;
4118 procedure ApplyFont2Wnd;
4119 procedure DoClick;
4121 function TBAddInsButtons( Idx: Integer; const Buttons: array of PChar; const BtnImgIdxArray: array
4122 of Integer ): Integer; stdcall;
4123 procedure SetBitBtnDrawMnemonic(const Value: Boolean);
4124 function GetBitBtnImgIdx: Integer;
4125 procedure SetBitBtnImgIdx(const Value: Integer);
4126 function GetBitBtnImageList: THandle;
4127 procedure SetBitBtnImageList(const Value: THandle);
4129 function GetModal: Boolean;
4130 {$IFDEF USE_SETMODALRESULT}
4131 procedure SetModalResult( const Value: Integer );
4132 {$ENDIF}
4134 protected
4135 fHandle: HWnd;
4136 fFocusHandle: HWnd;
4137 fClsStyle: DWord;
4138 fStyle: DWord;
4139 fExStyle: DWord;
4140 fCursor: HCursor;
4141 fCursorShared: Boolean;
4142 fIcon: HIcon;
4143 fIconShared: Boolean;
4144 fCaption: PChar; // it is now preferred to store Caption as PChar (null-
4145 // terminated string), dynamically allocated in memory.
4146 fIgnoreWndCaption: Boolean;
4148 fWindowState: TWindowState;
4149 fShowAction: Integer;
4150 fCanvas: PCanvas;
4151 fDefWndProc: Pointer;
4152 fNCDestroyed: Boolean;
4154 FParent: PControl;
4155 //FTag: Integer;
4156 fEnabled: Boolean; // Caution!!! fVisible must follow fEnabled! ___
4157 fVisible: Boolean; //____________________________________________//
4158 fTabstop: Boolean;
4159 fTabOrder: Integer;
4160 fTextAlign: TTextAlign;
4161 fVerticalAlign: TVerticalAlign;
4162 fWordWrap: Boolean;
4163 fPreventResize: Boolean;
4164 fAlphaBlend: Integer;
4165 FDroppedWidth: Integer;
4167 fChildren: PList;
4168 {* List of children. }
4169 fMDIClient: PControl;
4170 {* MDI client window control }
4171 fPass2DefProc: function( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
4172 {* MDI children list }
4173 fMDIChildren: PList;
4174 {* List of MDI children. It is filled for MDI client window. }
4175 fWndFunc: Pointer;
4176 {* Initially pointer to WndFunc. For MDI child window, points to DefMDIChildProc. }
4177 fExMsgProc: function( Applet: PControl; var Msg: TMsg ): Boolean;
4178 {* Additional message handler called directly from Applet.ProcessMessage.
4179 Used to call TranslateMDISysAccel API function for MDI application. }
4180 fMDIDestroying: Boolean;
4181 {* }
4183 fTmpBrush: HBrush;
4184 {* Brush handle to return in response to some color set messages.
4185 Intended for internal use instead of Brush.Color if possible
4186 to avoid using it. }
4187 fTmpBrushColorRGB: TColor;
4189 fMembersCount: Integer;
4190 {* Memebers count is first used in XCustomControl to separate
4191 some internal child controls from common XControl.Children
4192 and make it invisible among Children[]. }
4193 fDrawCtrl1st: PControl;
4194 {* Child control to draw it first, i.e. foreground of others. }
4195 FCreating: Boolean;
4196 {* True, when creating of object is in progress. }
4197 fDestroying: Boolean;
4198 {* True, when destroying of the window is started. Made protected to
4199 be accessible in descending classes. }
4200 fMenu: HMenu;
4201 {* Usually used to store handle of attached main menu, but sometimes
4202 is used to store control ID (for standard GUI controls only). }
4203 fMenuObj: PObj;
4204 {* PMenu pointer to TMenu object. Freed automatically with entire
4205 chain of menu objects attached to a control (or form). }
4206 {$IFNDEF NEW_MENU_ACCELL}
4207 fAccelTable: HAccel;
4208 {$ENDIF}
4209 {* Handle of accelerator table created by menu(s). }
4210 fImageList: PImageList;
4211 {* Pointer to first private image list. Control can own several image,
4212 lists, linked to a chain of image list objects. All these image lists
4213 are released automatically, when control is destroyed. }
4214 fCtlImageListSml: PImageList;
4215 {* ImageList object (with small icons 16x16) to use with a control (e.g.,
4216 with ListView control).
4217 If not set, but control has a list of image list objects, last added
4218 image list with small icons is used automatically. }
4219 fCtlImageListNormal: PImageList;
4220 {* ImageList object (with big icons 32x32) to use with a control.
4221 If not set, last added image list with big icons is used. }
4222 fCtlImgListState: PImageList;
4223 {* ImageList object to use as a state image list (for ListView control). }
4224 fIsApplet: Boolean;
4225 {* True, if the object represent application taskbar button. }
4226 fIsForm: Boolean;
4227 {* True, if the object is form. }
4228 fIsMDIChild: Boolean;
4229 {* TRUE, if the object is MDI child form. }
4230 fIsControl: Boolean;
4231 {* True, if it is a control on form. }
4232 fIsStaticControl: Boolean;
4233 {* True, if it is static control with a caption. (To prevent flickering
4234 it in DoubleBuffered mode. }
4235 fIsCommonControl: Boolean;
4236 {* True, if it is common control. }
4237 fChangedPosSz: Byte;
4238 {* Flags of changing left (1), top (2), width (4) or height (8) }
4239 fCannotDoubleBuf: Boolean;
4240 {* True, if cannot set DoubleBuffered to True (RichEdit). }
4241 fUpdRgn: HRgn;
4242 fCollectUpdRgn: HRGN;
4243 fEraseUpdRgn: Boolean;
4244 fPaintDC: HDC;
4245 fDblBufBmp: HBitmap;
4246 {* Memory bitmap, used for DoubleBuffered painting. }
4247 fDblBufW, fDblBufH: Integer;
4248 {* Dimensions of fDblBufBmp. }
4249 fDblBufPainting: Boolean;
4250 fLookTabKeys: TTabKeys;
4251 fNotUpdate: Boolean;
4252 fDynHandlers: PList;
4253 fColumn: Integer;
4254 FSupressTab: Boolean;
4255 fUpdateCount: Integer;
4256 fPaintLater: Boolean;
4257 fOnLeave: TOnEvent;
4258 fEditing: Boolean;
4259 fAutoPopupMenu: PObj;
4260 fHelpContext: Integer;
4262 // Order of following fields is important:
4263 //_______________________________________________________________________________________________
4264 fOnDynHandlers: TWindowFunc; //
4265 fWndProcKeybd: function( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; //
4266 fControlClick: procedure( Sender : PObj ); //
4267 fControlClassName: PChar; //
4268 fWindowed: Boolean; //
4269 {* True, if control is windowed (or is a form). Now always True, //
4270 because KOL does not yet contain Graphic controls. } //
4271 // //
4272 fCtlClsNameChg: Boolean; //
4273 {* True, if control class name changed and memory is allocated to store it. } //
4274 fWndProcResizeFlicks: function( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; //
4275 fGotoControl: function( Self_: PControl; Key: DWORD; CheckOnly: Boolean ): Boolean; //
4276 fCtl3Dchild: Boolean; //
4277 fCtl3D: Boolean; //
4278 fTextColor: TColor; //
4279 {* Color of text. Used instead of fFont.Color internally to //
4280 avoid usage of Font object if user is not accessing and changing it. } //
4281 fFont: PGraphicTool; //
4282 fColor: TColor; //
4283 {* Color of control background. } //
4284 fBrush: PGraphicTool; //
4285 fMargin: Integer; //
4286 fBoundsRect: TRect; //
4287 fClientTop, fClientBottom, fClientLeft, fClientRight: Integer; //
4288 {* Store adjustment factor of ClientRect for some 'idiosincrasies' windows, //
4289 such as Groupbox or Tabcontrol. } //
4290 //_____________________________________________________________________________________________//
4291 // this is the end of fiels set, which order is important
4293 fDoubleBuffered: Boolean; //
4294 fTransparent: Boolean; //
4296 fOnMessage: TOnMessage;
4297 fOldOnMessage: TOnMessage;
4299 fOnClick: TOnEvent;
4300 fRightClick: Boolean;
4301 fCurrentControl: PControl;
4302 fCreateVisible, fCreateHidden: Boolean;
4303 fRadio1st, fRadioLast : THandle;
4304 fDropDownProc: procedure( Sender : PObj );
4305 fDropped: Boolean;
4306 fCurIdxAtDrop: Integer;
4307 fPrevWndProc: Pointer;
4308 fClickDisabled: Byte;
4309 fCurItem, fCurIndex: Integer;
4310 FOnScroll: TOnScroll;
4311 FScrollLineDist: array[ 0..1 ] of Integer;
4313 fDefaultBtn: Boolean;
4314 fCancelBtn: Boolean;
4315 fDefaultBtnCtl: PControl;
4316 fCancelBtnCtl: PControl;
4317 fAllBtnReturnClick: Boolean;
4318 fIgnoreDefault: Boolean;
4320 fOnMouseDown: TOnMouse; // CAUTION!!! Order of mouse event handlers is important. ____
4321 fOnMouseUp: TOnMouse; //
4322 fOnMouseMove: TOnMouse; //
4323 fOnMouseDblClk: TOnMouse; //
4324 fOnMouseWheel: TOnMouse; //_____________________________________________________//
4326 fOldDefWndProc: Pointer;
4328 fOnChange: TOnEvent;
4329 fOnEnter: TOnEvent;
4331 FOnLVCustomDraw: TOnLVCustomDraw;
4332 FOnSBBeforeScroll: TOnSBBeforeScroll;
4333 FOnSBScroll: TOnSBScroll;
4334 protected
4335 procedure SetOnLVCustomDraw(const Value: TOnLVCustomDraw);
4336 public
4337 fCommandActions: TCommandActions;
4338 protected
4339 fOnChar: TOnChar;
4340 fOnKeyUp: TOnKey;
4341 fOnKeyDown: TOnKey;
4343 fOnPaint: TOnPaint;
4345 FMaxWidth: Integer;
4346 FMinWidth: Integer;
4347 FMaxHeight: Integer;
4348 FMinHeight: Integer;
4349 fShadowDeep: Integer;
4350 fStatusCtl: PControl;
4351 fStatusWnd: HWnd;
4352 fStatusTxt: PChar;
4353 fColor1: TColor;
4354 fColor2: TColor;
4355 fLVColCount: Integer;
4356 fLVOptions: TListViewOptions;
4357 fLVStyle: TListViewStyle;
4358 fOnEditLVITem: TOnEditLVItem;
4359 fLVTextBkColor: TColor;
4360 fLVItemHeight: Integer;
4362 fOnDropDown: TOnEvent;
4363 fOnCloseUp: TOnEvent;
4365 fModalResult: Integer;
4367 fModal: Integer;
4368 fModalForm: PControl;
4370 FAlign: TControlAlign;
4371 fNotUseAlign: Boolean;
4372 fDragCallback: TOnDrag;
4373 fDragging: Boolean;
4374 fDragStartPos: TPoint;
4375 fMouseStartPos: TPoint;
4376 fSplitStartPos: TPoint;
4377 fSplitStartPos2: TPoint;
4378 fSplitStartSize: Integer;
4379 fSplitMinSize1, fSplitMinSize2: Integer;
4380 fOnSplit: TOnSplit;
4381 fSecondControl: PControl;
4382 fOnSelChange: TOnEvent;
4383 fTmpFont: PGraphicTool;
4385 fRECharFormatRec: TCharFormat2;
4386 fREError: Integer;
4387 fREStream: PStream;
4388 fREStrLoadLen: DWORD;
4389 fREParaFmtRec: TParaFormat2;
4390 FOnResize: TOnEvent;
4391 fOnProgress: TOnEvent;
4392 fCharFmtDeltaSz: Integer;
4393 fParaFmtDeltaSz: Integer;
4394 fREOvr: Boolean;
4395 fReOvrDisable: Boolean;
4396 fOnREInsModeChg: TOnEvent;
4397 fREScrolling: Boolean;
4398 fUpdCount: Integer;
4399 fOnREOverURL: TOnEvent;
4400 fOnREURLClick: TOnEvent;
4401 fRECharArea: TRichFmtArea;
4402 fBitBtnOptions : TBitBtnOptions;
4403 fGlyphLayout : TGlyphLayout;
4404 fGlyphBitmap : HBitmap;
4405 fGlyphCount : Integer;
4406 fGlyphWidth, fGlyphHeight: Integer;
4407 fOnBitBtnDraw: TOnBitBtnDraw;
4408 fFlat: Boolean;
4409 fSizeRedraw: Boolean; {YS}
4411 fOnMouseLeave: TOnEvent;
4412 fOnMouseEnter: TOnEvent;
4413 fOnTestMouseOver: TOnTestMouseOver;
4415 fMouseInControl: Boolean;
4416 fRepeatInterval: Integer;
4417 fChecked: Boolean;
4418 fPrevFocusWnd: HWnd;
4420 fOnTVBeginDrag: TOnTVBeginDrag;
4421 fOnTVBeginEdit: TOnTVBeginEdit;
4422 fOnTVEndEdit: TOnTVEndEdit;
4423 fOnTVExpanded: TOnTVExpanded;
4424 fOnTVExpanding: TOnTVExpanding;
4425 fOnTVDelete: TOnTVDelete;
4427 fOnDeleteLVItem: TOnDeleteLVItem;
4428 fOnDeleteAllLVItems: TOnEvent;
4429 fOnLVData: TOnLVData;
4430 {$IFNDEF _FPC}
4431 {$IFNDEF _D2}
4432 fOnLVDataW: TOnLVDataW;
4433 {$ENDIF _D2}
4434 {$ENDIF _FPC}
4435 fOnCompareLVItems: TOnCompareLVItems;
4436 fOnColumnClick: TOnLVColumnClick;
4437 fOnDrawItem: TOnDrawItem;
4438 fOnMeasureItem: TOnMeasureItem;
4439 fREUrl: String;
4440 FMinimizeWnd: PControl;
4441 FFixWidth: Integer;
4442 FFixHeight: Integer;
4443 FOnDropFiles: TOnDropFiles;
4444 FOnHide: TOnEvent;
4445 FOnShow: TOnEvent;
4446 fOnEraseBkgnd: TOnPaint;
4447 fCustomData: Pointer;
4448 fCustomObj: PObj;
4449 fOnTVSelChanging: TOnTVSelChanging;
4451 fOnClose: TOnEventAccept;
4452 fOnQueryEndSession: TOnEventAccept;
4453 fCloseQueryReason: TCloseQueryReason;
4455 //----- order of following 3 events important: //
4456 fOnMinimize: TOnEvent; //
4457 fOnMaximize: TOnEvent; //
4458 fOnRestore: TOnEvent; //
4459 //---------------------------------------------//
4461 //fCreateParamsExt: procedure( Self_: PControl; var Params: TCreateParams );
4462 fCreateWndExt: procedure( Sender: PControl );
4464 fTBttCmd: PList;
4465 fTBttTxt: PStrList;
4466 fTBevents: PList; // events for TBAssignEvents
4467 fTBBtnImgWidth: Integer; // custom toolbar bitmap width
4468 FTBBtMinWidth: Integer;
4469 FTBBtMaxWidth: Integer;
4470 fGradientStyle: TGradientStyle;
4471 fGradientLayout: TGradientLayout;
4472 fVisibleWoParent: Boolean;
4475 fTVRightClickSelect: Boolean;
4476 FOnMove: TOnEvent;
4477 FOnLVStateChange: TOnLVStateChange;
4478 FOnLVDelete: TOnLVDelete;
4479 fAutoSize: procedure( Self_: PControl );
4480 fIsButton: Boolean;
4481 fSizeGrip: Boolean;
4482 fNotAvailable: Boolean;
4483 FPressedMnemonic: DWORD;
4484 FBitBtnDrawMnemonic: Boolean;
4485 FBitBtnGetCaption: function( Self_: PControl; const S: String ): String;
4486 FBitBtnExtDraw: procedure( Self_: PControl; DC: HDC; X, Y: Integer; const R: TRect;
4487 const CapText, CapTxtOrig: String; Color: TColor );
4488 FTextShiftX, FTextShiftY: Integer;
4489 fNotifyChild: procedure( Self_, Child: PControl );
4490 fScrollChildren: procedure( Self_: PControl );
4491 fOnHelp: TOnHelp;
4493 FOnDTPUserString: TDTParseInputEvent;
4495 {$IFDEF USE_MHTOOLTIP}
4496 {$DEFINE var}
4497 {$I KOLMHToolTip}
4498 {$UNDEF var}
4500 {$DEFINE function}
4501 {$I KOLMHToolTip}
4502 {$UNDEF function}
4503 {$ENDIF}
4505 procedure Init; {-}virtual;{+}{++}(*override;*){--}
4506 {* }
4507 procedure InitParented( AParent: PControl ); virtual;
4508 {* Initialization of visual object. }
4509 procedure DestroyChildren;
4510 {* Destroys children. Is called in destructor, and can be
4511 called in descending classes as earlier as needed to
4512 prevent problems of too late destroying of visuals. }
4514 function GetParentWnd( NeedHandle: Boolean ): HWnd;
4515 {* Returns handle of parent window. }
4516 function GetParentWindow: HWnd;
4517 {* }
4518 procedure SetEnabled( Value: Boolean );
4519 {* Changes Enabled property value. Overriden here to change enabling
4520 status of a window. }
4521 function GetEnabled: Boolean;
4522 {* Returns True, if Enabled. Overriden here to obtain real window
4523 state. }
4524 procedure SetVisible( Value: Boolean );
4525 {* Sets Visible property value. Overriden here to change visibility
4526 of correspondent window. }
4527 procedure Set_Visible( Value: Boolean );
4528 {* }
4529 function GetVisible: Boolean;
4530 {* Returns True, if correspondent window is Visible. Overriden
4531 to get visibility of real window, not just value stored in object. }
4532 function Get_Visible: Boolean;
4533 {* Returns True, if correspondent window is Visible, for forms and applet,
4534 or if fVisible flag is set, for controls. }
4535 procedure SetCtlColor( Value: TColor );
4536 {* Sets TControl's Color property value. }
4537 procedure SetBoundsRect( const Value: TRect );
4538 {* Sets BoudsRect property value. }
4539 function GetBoundsRect: TRect;
4540 {* Returns bounding rectangle. }
4541 function GetIcon: HIcon;
4542 {* Returns Icon property. By default, if it is not set,
4543 returns Icon property of an Applet. }
4545 procedure CreateSubclass( var Params: TCreateParams; ControlClassName: PChar );
4546 {* Can be used in descending classes to subclass window with given
4547 standard Windows ControlClassName - must be called after
4548 creating Params but before CreateWindow. Usually it is called
4549 in overriden method CreateParams after calling of the inherited one. }
4551 function UpdateWndStyles: PControl;
4552 {* Updates fStyle, fExStyle, fClsStyle from window handle }
4553 procedure SetOnChar(const Value: TOnChar);
4554 {* }
4555 procedure SetOnKeyDown(const Value: TOnKey);
4557 {* }
4558 procedure SetOnKeyUp(const Value: TOnKey);
4559 {* }
4560 procedure SetMouseDown(const Value: TOnMouse);
4561 {* }
4562 procedure SetMouseMove(const Value: TOnMouse);
4563 {* }
4564 procedure SetMouseUp(const Value: TOnMouse);
4565 {* }
4566 procedure SetMouseWheel(const Value: TOnMouse);
4567 {* }
4568 procedure SetMouseDblClk(const Value: TOnMouse);
4569 {* }
4570 procedure SetHelpContext( Value: Integer );
4571 {* }
4572 procedure SetOnTVDelete( const Value: TOnTVDelete );
4573 {* }
4574 procedure SetDefaultBtn(const Index: Integer; const Value: Boolean);
4575 {$IFDEF F_P}
4576 function GetDefaultBtn(const Index: Integer): Boolean;
4577 {$ENDIF F_P}
4578 function DefaultBtnProc( var Msg: TMsg; var Rslt: Integer ): Boolean;
4579 {* }
4581 procedure SetDateTime( Value: TDateTime );
4582 function GetDateTime: TDateTime;
4583 procedure SetDateTimeRange( Value: TDateTimeRange );
4584 function GetDateTimeRange: TDateTimeRange;
4585 procedure SetDateTimePickerColor( Index: TDateTimePickerColor; Value: TColor );
4586 function GetDateTimePickerColor( Index: TDateTimePickerColor ): TColor;
4587 procedure SetDateTimeFormat( const Value: String );
4589 public
4590 constructor CreateParented( AParent: PControl );
4591 {* Creates new instance of TControl object, calling InitParented }
4592 //FormPointer_DoNotUseItPlease_ItIsUsedByMCK: Pointer;
4593 { ^ no more needed }
4594 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
4595 {* Destroyes object. First of all, destructors for all children
4596 are called. }
4598 function GetWindowHandle: HWnd;
4599 {* Returns window handle. If window is not yet created,
4600 method CreateWindow is called. }
4601 procedure CreateChildWindows;
4602 {* Enumerates all children recursively and calls CreateWindow for all
4603 of these. }
4604 property Parent: PControl read fParent write SetParent;
4605 {* Parent of TParent object. Also must be of TParent type or derived from TParent. }
4606 //property Tag: Integer read FTag write FTag; //--------- moved to TObj --------
4607 {* User-defined pointer, which can contain any data or reference to
4608 anywhere in memory (when used as a pointer).
4610 function ChildIndex( Child: PControl ): Integer;
4611 {* Returns index of given child. }
4612 procedure MoveChild( Child: PControl; NewIdx: Integer );
4613 {* Moves given Child into new position. }
4615 property Enabled: Boolean read GetEnabled write SetEnabled;
4616 {* Enabled usually used to decide if control can get keyboard focus
4617 or been clicked by mouse. }
4618 procedure EnableChildren( Enable, Recursive: Boolean );
4619 {* Enables (Enable = TRUE) or disables (Enable = FALSE) all the children
4620 of the control. If Recursive = TRUE then all the children of all the
4621 children are enabled or disabled recursively. }
4622 property Visible: Boolean read Get_Visible write SetVisible;
4623 {* Obvious. }
4624 property ToBeVisible: Boolean read GetToBeVisible;
4625 {* Returns True, if a control is supposed to be visible when its
4626 form is showing. Thus is, True is returned if either control
4627 is Visible or hidden, but marked with flag fCreateHidden. }
4628 property CreateVisible: Boolean read fCreateVisible write fCreateVisible;
4629 {* False by default. If You want your form to be created visible and
4630 flick due creation, set it to True. This does not affect size of
4631 executable anyway. }
4632 property Align: TControlAlign read FAlign write Set_Align;
4633 {* Align style of a control. If this property is not used in your
4634 application, there are no additional code added. Aligning of
4635 controls is made in KOL like in VCL. To align controls when
4636 initially create ones, use "transparent" function SetAlign
4637 ("transparent" means that it returns @Self as a result).
4638 |<br>
4639 Note, that it is better not to align combobox caClient, caLeft or
4640 caRight (better way is to place a panel with Border = 0 and
4641 EdgeStyle = esNone, align it as desired and to place a combobox on it
4642 aligning caTop or caBottom). Otherwise, big problems could be under
4643 Win9x/Me, and some delay could occur under any other systems.
4644 |<br> Do not attempt to align some kinds of controls (like combobox or
4645 toolbar) caLeft or caRight, this can cause infinite recursion in the
4646 application. }
4647 property BoundsRect: TRect read GetBoundsRect write SetBoundsRect;
4648 {* Bounding rectangle of the visual. Coordinates are relative
4649 to top left corner of parent's ClientRect, or to top left corner
4650 of screen (for TForm). }
4651 property Left: Integer read GetLeft write SetLeft;
4652 {* Left horizontal position. }
4653 property Top: Integer read GetTop write SetTop;
4654 {* Top vertical position. }
4655 property Width: Integer read GetWidth write SetWidth;
4656 {* Width of TVisual object. }
4657 property Height: Integer read GetHeight write SetHeight;
4658 {* Height of TVisual object. }
4660 property Position: TPoint read GetPosition write Set_Position;
4661 {* Represents top left position of the object. See also BoundsRect. }
4662 property MinWidth: Integer index 0
4663 {$IFDEF F_P} read GetConstraint
4664 {$ELSE DELPHI} read FMinWidth
4665 {$ENDIF F_P/DELPHI} write SetConstraint;
4666 {* Minimal width constraint. }
4667 property MinHeight: Integer index 1
4668 {$IFDEF F_P} read GetConstraint
4669 {$ELSE DELPHI} read FMinHeight
4670 {$ENDIF F_P/DELPHI} write SetConstraint;
4671 {* Minimal height constraint. }
4672 property MaxWidth: Integer index 2
4673 {$IFDEF F_P} read GetConstraint
4674 {$ELSE DELPHI} read FMaxWidth
4675 {$ENDIF F_P/DELPHI} write SetConstraint;
4676 {* Maximal width constraint. }
4677 property MaxHeight: Integer index 3
4678 {$IFDEF F_P} read GetConstraint
4679 {$ELSE DELPHI} read FMaxHeight
4680 {$ENDIF F_P/DELPHI} write SetConstraint;
4681 {* Maximal height constraint. }
4683 function ClientRect: TRect;
4684 {* Client rectangle of TVisual. Contrary to VCL, for some
4685 classes (e.g., derived from XCustomControl, can be relative
4686 not to itself, but to top left corner of the BoundsRect
4687 rectangle. }
4688 property ClientWidth: Integer read GetClientWidth write SetClientWidth;
4689 {* Obvious. Accessing this property, program forces window latent creation. }
4690 property ClientHeight: Integer read GetClientHeight write SetClientHeight;
4691 {* Obvious. Accessing this property, program forces window latent creation. }
4693 function ControlRect: TRect;
4694 {* Absolute bounding rectangle relatively to nearest
4695 Windowed parent client rectangle (at least to a form, but usually to
4696 a Parent).
4697 Useful while drawing on device context, provided by such
4698 Windowed parent. For form itself is the same as BoundsRect. }
4699 function ControlAtPos( X, Y: Integer; IgnoreDisabled: Boolean ): PControl;
4700 {* Searches TVisual at the given position (relatively to top left
4701 corner of the ClientRect). }
4703 procedure Invalidate;
4704 {* Invalidates rectangle, occupied by the visual (but only if Showing =
4705 True). }
4707 procedure InvalidateEx;
4708 {* Invalidates the window and all its children. }
4709 procedure InvalidateNC( Recursive: Boolean );
4710 {* Invalidates the window and all its children including non-client area. }
4711 procedure Update;
4712 {* Updates control's window and calls Update for all child controls. }
4713 procedure BeginUpdate;
4714 {* |<#treeview>
4715 |<#listview>
4716 |<#richedit>
4717 |<#memo>
4718 |<#listbox>
4719 Call this method to stop visual updates of the control until correspondent
4720 EndUpdate called (pairs BeginUpdate - EndUpdate can be nested). }
4721 procedure EndUpdate;
4722 {* See BeginUpdate. }
4724 property Windowed: Boolean read fWindowed;
4725 {* Constantly returns True, if object is windowed (i.e. owns
4726 correspondent window handle). Otherwise, returns False.
4727 |<br>
4728 By now, all the controls are windowed (there are no controls in KOL, which are
4729 emulating window, acually belonging to Parent - like TGraphicControl
4730 in VCL). }
4732 function HandleAllocated: Boolean;
4733 {* Returns True, if window handle is allocated. Has no sense for
4734 non-Windowed objects (but now, the KOL has no non-Windowed controls). }
4735 property MDIClient: PControl read fMDIClient;
4736 {* For MDI forms only: returns MDI client window control, containng all MDI
4737 children. Use this window to send specific messages to rule MDI children. }
4739 property ChildCount: Integer read GetChildCount;//GetChildCountWOMembers;
4740 {* Returns number of commonly accessed child objects (without
4741 MembersCount). }
4742 property Children[ Idx: Integer ]: PControl read GetMembers;
4743 {* Child items of TVisual object. Property is reintroduced here
4744 to separate access to always visible Children[] from restricted
4745 a bit Members[]. }
4746 property MembersCount: Integer read FMembersCount;
4747 {* Returns number of "internal" child objects, which are
4748 not accessible through common Children[] property. }
4749 property Members[ Idx: Integer ]: PControl read GetMembers;
4750 {* Members and children array of the object (first from 0 to
4751 MembersCount-1 are Members[], and Children[] are followed by
4752 them. Usually You do not need to use this list. Use instead
4753 Children[0..ChildCount] property, Members[] is intended for
4754 internal needs of XCL (and in KOL by now Members and Children
4755 actually are the same properties). }
4757 procedure PaintBackground( DC: HDC; Rect: PRect );
4758 {* Is called to paint background in given rectangle. This
4759 method is filling clipped area of the Rect rectangle with
4760 Color, but only if global event Global_OnPaintBkgnd is
4761 not assigned. If assigned, this one is called instead here.
4762 |<br>&nbsp;&nbsp;&nbsp;
4763 This method made public, so it can be called directly to
4764 fill some device context's rectangle. But remember, that
4765 independantly of Rect, top left corner of background piece
4766 will be located so, if drawing is occure into ControlRect
4767 rectangle. }
4768 property WindowedParent: PControl read fParent;
4769 {* Returns nearest windowed parent, the same as Parent. }
4771 function ParentForm: PControl;
4772 {* |<#form>
4773 Returns parent form for a control (of @Self for form itself. }
4774 property ActiveControl: PControl read fCurrentControl write fCurrentControl;
4775 {* }
4776 function Client2Screen( const P: TPoint ): TPoint;
4777 {* Converts the client coordinates of a specified point to screen coordinates. }
4778 function Screen2Client( const P: TPoint ): TPoint;
4779 {* Converts screen coordinates of a specified point to client coordinates. }
4780 function CreateWindow: Boolean; virtual;
4781 {* |<#form>
4782 Creates correspondent window object. Returns True if success (if
4783 window is already created, False is returned). If applied to a form,
4784 all child controls also allocates handles that time.
4785 |<br>&nbsp;&nbsp;&nbsp;
4786 Call this method to ensure, that a hanle is allocated for a form,
4787 an application button or a control. (It is not necessary to do so in
4788 the most cases, even if You plan to work with control's handle directly.
4789 But immediately after creating the object, if You want to pass its
4790 handle to API function, this can be helpful). }
4791 procedure Close;
4792 {* |<#appbutton>
4793 |<#form>
4794 Closes window. If a window is the main form, this closes application,
4795 terminating it. Also it is possible to call Close method for Applet
4796 window to stop application. }
4798 {$IFDEF USE_MHTOOLTIP}
4799 {$DEFINE public}
4800 {$I KOLMHToolTip}
4801 {$UNDEF public}
4802 {$ENDIF}
4804 property Handle: HWnd read fHandle; //GetHandle;
4805 {* Returns descriptor of system window object. If window is not yet
4806 created, 0 is returned. To allocate handle, call CreateWindow method. }
4808 property ParentWindow: HWnd read GetParentWindow;
4809 {* Returns handle of parent window (not TControl object, but system
4810 window object handle). }
4811 property ClsStyle: DWord read fClsStyle write SetClsStyle;
4812 {* Window class style. Available styles are:
4813 |<table border=0>
4814 |&L=<tr><td valign=top><font face=Fixedsys>%1</font></td><td>
4815 |&E=</td></tr>
4816 |&N=<br>&nbsp;&nbsp;&nbsp;
4817 <L CS_BYTEALIGNCLIENT> - Aligns the window's client area on the byte boundary
4818 (in the x direction) to enhance performance during
4819 drawing operations. <E>
4820 <L CS_BYTEALIGNWINDOW> - Aligns a window on a byte boundary (in the x
4821 direction). <E>
4822 <L CS_CLASSDC> - Allocates one device context to be shared by all
4823 windows in the class. <E>
4824 <L CS_DBLCLKS> - Sends double-click messages to the window
4825 procedure when the user double-clicks the mouse while the
4826 cursor is within a window belonging to the class. <E>
4827 <L CS_GLOBALCLASS> - Allows an application to create a window of
4828 the class regardless of the value of the hInstance parameter.
4829 <N> You can create a global class by creating
4830 the window class in a dynamic-link library (DLL) and listing the
4831 name of the DLL in the registry under specific keys. <E>
4832 <L CS_HREDRAW> - Redraws the entire window if a movement or
4833 size adjustment changes the width of the client area. <E>
4834 <L CS_NOCLOSE> - Disables the Close command on the System menu. <E>
4835 <L CS_OWNDC> - Allocates a unique device context for each window
4836 in the class. <E>
4837 <L CS_PARENTDC> - Sets the clipping region of the child window to
4838 that of the parent window so that the child can draw on the parent. <E>
4839 <L CS_SAVEBITS> - Saves, as a bitmap, the portion of the screen
4840 image obscured by a window. Windows uses the saved bitmap to re-create
4841 the screen image when the window is removed. <E>
4842 <L CS_VREDRAW> - Redraws the entire window if a movement or size
4843 adjustment changes the height of the client area. <E>
4844 |</table> For more info, see Win32.hlp (keyword 'WndClass');
4847 property Style: DWord read fStyle write SetStyle;
4848 {* Window styles. Available styles are:
4849 |<table border=0>
4850 <L WS_BORDER> Creates a window that has a thin-line border. <E>
4851 <L WS_CAPTION> Creates a window that has a title bar (includes the
4852 WS_BORDER style). <E>
4853 <L WS_CHILD> Creates a child window. This style cannot be used with
4854 the WS_POPUP style. <E>
4855 <L WS_CHILDWINDOW> Same as the WS_CHILD style. <E>
4856 <L WS_CLIPCHILDREN> Excludes the area occupied by child windows
4857 when drawing occurs within the parent window. This style is used
4858 when creating the parent window. <E>
4859 <L WS_CLIPSIBLINGS> Clips child windows relative to each other;
4860 that is, when a particular child window receives a WM_PAINT message,
4861 the WS_CLIPSIBLINGS style clips all other overlapping child windows
4862 out of the region of the child window to be updated. If
4863 WS_CLIPSIBLINGS is not specified and child windows overlap, it is
4864 possible, when drawing within the client area of a child window,
4865 to draw within the client area of a neighboring child window. <E>
4866 <L WS_DISABLED> Creates a window that is initially disabled. A
4867 disabled window cannot receive input from the user. <E>
4868 <L WS_DLGFRAME> Creates a window that has a border of a style
4869 typically used with dialog boxes. A window with this style cannot
4870 have a title bar. <E>
4871 <L WS_GROUP> Specifies the first control of a group of controls.
4872 The group consists of this first control and all controls defined
4873 after it, up to the next control with the WS_GROUP style.
4874 The first control in each group usually has the WS_TABSTOP
4875 style so that the user can move from group to group. The user
4876 can subsequently change the keyboard focus from one control in
4877 the group to the next control in the group by using the direction
4878 keys. <E>
4879 <L WS_HSCROLL> Creates a window that has a horizontal scroll bar. <E>
4880 <L WS_ICONIC> Creates a window that is initially minimized. Same as
4881 the WS_MINIMIZE style. <E>
4882 <L WS_MAXIMIZE> Creates a window that is initially maximized. <E>
4883 <L WS_MAXIMIZEBOX> Creates a window that has a Maximize button.
4884 Cannot be combined with the WS_EX_CONTEXTHELP style. The WS_SYSMENU
4885 style must also be specified. <E>
4886 <L WS_MINIMIZE> Creates a window that is initially minimized.
4887 Same as the WS_ICONIC style. <E>
4888 <L WS_MINIMIZEBOX> Creates a window that has a Minimize button.
4889 Cannot be combined with the WS_EX_CONTEXTHELP style. The WS_SYSMENU
4890 style must also be specified. <E>
4891 <L WS_OVERLAPPED> Creates an overlapped window. An overlapped
4892 window has a title bar and a border. Same as the WS_TILED style. <E>
4893 <L WS_OVERLAPPEDWINDOW> Creates an overlapped window with the
4894 WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU, WS_THICKFRAME, WS_MINIMIZEBOX,
4895 and WS_MAXIMIZEBOX styles. Same as the WS_TILEDWINDOW style. <E>
4896 <L WS_POPUP> Creates a pop-up window. This style cannot be used with
4897 the WS_CHILD style. <E>
4898 <L WS_POPUPWINDOW> Creates a pop-up window with WS_BORDER,
4899 WS_POPUP, and WS_SYSMENU styles. The WS_CAPTION and WS_POPUPWINDOW
4900 styles must be combined to make the window menu visible. <E>
4901 <L WS_SIZEBOX> Creates a window that has a sizing border. Same as the
4902 WS_THICKFRAME style. <E>
4903 <L WS_SYSMENU> Creates a window that has a window-menu on its title
4904 bar. The WS_CAPTION style must also be specified. <E>
4905 <L WS_TABSTOP> Specifies a control that can receive the keyboard focus
4906 when the user presses the TAB key. Pressing the TAB key changes
4907 the keyboard focus to the next control with the WS_TABSTOP style. <E>
4908 <L WS_THICKFRAME> Creates a window that has a sizing border.
4909 Same as the WS_SIZEBOX style. <E>
4910 <L WS_TILED> Creates an overlapped window. An overlapped window has
4911 a title bar and a border. Same as the WS_OVERLAPPED style. <E>
4912 <L WS_TILEDWINDOW> Creates an overlapped window with the
4913 WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU, WS_THICKFRAME,
4914 WS_MINIMIZEBOX, and WS_MAXIMIZEBOX styles. Same as the
4915 WS_OVERLAPPEDWINDOW style. <E>
4916 <L WS_VISIBLE> Creates a window that is initially visible. <E>
4917 <L WS_VSCROLL> Creates a window that has a vertical scroll bar. <E>
4918 |</table>
4919 See also Win32.hlp (topic CreateWindow).
4921 property ExStyle: DWord read fExStyle write SetExStyle;
4922 {* Extra window styles. Available flags are following:
4923 |<table border=0>
4924 <L WS_EX_ACCEPTFILES> Specifies that a window created with this style
4925 accepts drag-drop files. <E>
4926 <L WS_EX_APPWINDOW> Forces a top-level window onto the taskbar
4927 when the window is minimized. <E>
4928 <L WS_EX_CLIENTEDGE> Specifies that a window has a border with a
4929 sunken edge. <E>
4930 <L WS_EX_CONTEXTHELP> Includes a question mark in the title bar of
4931 the window. When the user clicks the question mark, the cursor
4932 changes to a question mark with a pointer. If the user then clicks
4933 a child window, the child receives a WM_HELP message. The child
4934 window should pass the message to the parent window procedure,
4935 which should call the WinHelp function using the HELP_WM_HELP
4936 command. The Help application displays a pop-up window that
4937 typically contains help for the child window.WS_EX_CONTEXTHELP
4938 cannot be used with the WS_MAXIMIZEBOX or WS_MINIMIZEBOX styles. <E>
4939 <L WS_EX_CONTROLPARENT> Allows the user to navigate among the child
4940 windows of the window by using the TAB key. <E>
4941 <L WS_EX_DLGMODALFRAME> Creates a window that has a double border;
4942 the window can, optionally, be created with a title bar by
4943 specifying the WS_CAPTION style in the dwStyle parameter. <E>
4944 <L WS_EX_LEFT> Window has generic "left-aligned" properties. This
4945 is the default. <E>
4946 <L WS_EX_LEFTSCROLLBAR> If the shell language is Hebrew, Arabic, or
4947 another language that supports reading order alignment, the
4948 vertical scroll bar (if present) is to the left of the client
4949 area. For other languages, the style is ignored and not treated
4950 as an error. <E>
4951 <L WS_EX_LTRREADING> The window text is displayed using Left to
4952 Right reading-order properties. This is the default. <E>
4953 <L WS_EX_MDICHILD> Creates an MDI child window. <E>
4954 <L WS_EX_NOPARENTNOTIFY> Specifies that a child window created
4955 with this style does not send the WM_PARENTNOTIFY message to its
4956 parent window when it is created or destroyed. <E>
4957 <L WS_EX_OVERLAPPEDWINDOW> Combines the WS_EX_CLIENTEDGE and
4958 WS_EX_WINDOWEDGE styles. <E>
4959 <L WS_EX_PALETTEWINDOW> Combines the WS_EX_WINDOWEDGE,
4960 WS_EX_TOOLWINDOW, and WS_EX_TOPMOST styles. <E>
4961 <L WS_EX_RIGHT> Window has generic "right-aligned" properties.
4962 This depends on the window class. This style has an effect only
4963 if the shell language is Hebrew, Arabic, or another language that
4964 supports reading order alignment; otherwise, the style is
4965 ignored and not treated as an error. <E>
4966 <L WS_EX_RIGHTSCROLLBAR> Vertical scroll bar (if present) is to the
4967 right of the client area. This is the default. <E>
4968 <L WS_EX_RTLREADING> If the shell language is Hebrew, Arabic, or
4969 another language that supports reading order alignment, the
4970 window text is displayed using Right to Left reading-order
4971 properties. For other languages, the style is ignored and not
4972 treated as an error. <E>
4973 <L WS_EX_STATICEDGE> Creates a window with a three-dimensional
4974 border style intended to be used for items that do not accept
4975 user input. <E>
4976 <L WS_EX_TOOLWINDOW> Creates a tool window; that is, a window
4977 intended to be used as a floating toolbar. A tool window has
4978 a title bar that is shorter than a normal title bar, and the
4979 window title is drawn using a smaller font. A tool window does
4980 not appear in the taskbar or in the dialog that appears when
4981 the user presses ALT+TAB. <E>
4982 <L WS_EX_TOPMOST> Specifies that a window created with this style
4983 should be placed above all non-topmost windows and should stay
4984 above them, even when the window is deactivated. To add or remove
4985 this style, use the SetWindowPos function. <E>
4986 <L WS_EX_TRANSPARENT> Specifies that a window created with this
4987 style is to be transparent. That is, any windows that are
4988 beneath the window are not obscured by the window. A window
4989 created with this style receives WM_PAINT messages only after
4990 all sibling windows beneath it have been updated. <E>
4991 <L WS_EX_WINDOWEDGE> Specifies that a window has a border with
4992 a raised edge. <E>
4993 |</table>
4994 See also Win32.hlp (topic CreateWindowEx).
4997 property Cursor: HCursor read fCursor write SetCursor;
4998 {* Current cursor. For most of controls, sets initially to IDC_ARROW. See
4999 also ScreenCursor. }
5000 procedure CursorLoad( Inst: Integer; ResName: PChar );
5001 {* Loads Cursor from the resource. See also comments for Icon property. }
5003 property Icon: HIcon read GetIcon write SetIcon;
5004 {* |<#appbutton>
5005 |<#form>
5006 Icon. By default, icon of the Applet is used. To load icon from the
5007 resource, use IconLoad or IconLoadCursor method - this is more correct, because
5008 in such case a special flag is set to prevent attempts to destroy
5009 shared icon object in the destructor of the control. }
5011 procedure IconLoad( Inst: Integer; ResName: PChar );
5012 {* |<#appbutton>
5013 |<#form>
5014 See Icon property. }
5015 procedure IconLoadCursor( Inst: Integer; ResName: PChar );
5016 {* |<#appbutton>
5017 |<#form>
5018 Loads Icon from the cursor resource. See also Icon property. }
5021 property Menu: HMenu read fMenu write SetMenu;
5023 {* Menu (or ID of control - for standard GUI controls). }
5024 property HelpContext: Integer read fHelpContext write SetHelpContext;
5025 {* Help context. }
5026 function AssignHelpContext( Context: Integer ): PControl;
5027 {* Assigns HelpContext and returns @ Self (can be used in initialization
5028 of a control in a chain of "transparent" calls). }
5030 procedure CallHelp( Context: Integer; CtxCtl: PControl {; CtlID: Integer} );
5031 {* Method of a form or Applet. Call it to show help with the given context
5032 ID. If the Context = 0, help contents is displayed. By default,
5033 WinHelp is used. To allow using HtmlHelp, call AssignHtmlHelp global
5034 function. When WinHelp used, HelpPath variable can be assigned directly.
5035 If HelpPath variable is not assigned, application name
5036 (and path) is used, with extension replaced to '.hlp'. }
5038 property HelpPath: String read GetHelpPath write SetHelpPath;
5039 {* Property of a form or an Applet. Change it to provide custom path to
5040 WinHelp format help file. If HtmlHelp used, call global procedure
5041 AssignHtmlHelp instead. }
5043 property OnHelp: TOnHelp read fOnHelp write fOnHelp;
5044 {* An event of a form, it is called when F1 pressed or help topic requested
5045 by any other way. To prevent showing help, nullify Sender. Set Popup to
5046 TRUE to provide showing help in a pop-up window. It is also possible to
5047 change Context dynamically. }
5049 property Caption: String read GetCaption write SetCaption;
5050 {* |<#appbutton>
5051 |<#form>
5052 |<#button>
5053 |<#bitbtn>
5054 |<#label>
5055 |<#wwlabel>
5056 |<#3dlabel>
5057 Caption of a window. For standard Windows buttons, labels and so on
5058 not a caption of a window, but text of the window. }
5059 property Text: String read GetCaption write SetCaption;
5060 {* |<#edit>
5061 |<#memo>
5062 The same as Caption. To make more convenient with Edit controls. For
5063 Rich Edit control, use property RE_Text. }
5064 property SelStart: Integer read GetSelStart write SetSelStart;
5065 {* |<#edit>
5066 |<#memo>
5067 |<#richedit>
5068 |<#listbox>
5069 |<#combo>
5070 Start of selection (editbox - character position, listbox and combobox -
5071 index of [the first] selected item). }
5072 property SelLength: Integer read GetSelLength write SetSelLength;
5073 {* |<#edit>
5074 |<#memo>
5075 |<#richedit>
5076 |<#listbox>
5077 |<#listview>
5078 Length of selection (editbox - number of characters selected, multiline
5079 listbox - number of items selected). }
5081 property Selection: String read GetSelection write SetSelection;
5082 {* |<#edit>
5083 |<#memo>
5084 |<#richedit>
5085 Selected text (editbox, richedit) as string. Can be useful to replace
5086 selection. For rich edit, use RE_Text[ reText, TRUE ], if you want to
5087 read correctly characters from another locale then ANSI only. }
5088 procedure SelectAll;
5089 {* |<#edit>
5090 |<#memo>
5091 |<#richedit>
5092 Makes all the text in editbox or RichEdit, or all items in listbox
5093 selected. }
5095 procedure ReplaceSelection( const Value: String; aCanUndo: Boolean );
5096 {* |<#edit>
5097 |<#memo>
5098 |<#richedit>
5099 Replaces selection (in edit, RichEdit). Unlike assigning new value
5100 to Selection property, it is possible to specify, if operation can
5101 be undone. }
5103 procedure DeleteLines( FromLine, ToLine: Integer );
5104 {* |<#edit>
5105 |<#memo>
5106 |<#richedit>
5107 Deletes lines from FromLine to ToLine (inclusively, i.e. 0 to 0 deletes
5108 one line with index 0). Current selection is restored as possible. }
5109 property CurIndex: Integer read GetCurIndex write SetCurIndex;
5110 {* |<#listbox>
5111 |<#combo>
5112 |<#toolbar>
5113 Index of current item (for listbox, combobox) or button index pressed
5114 or dropped down (for toolbar button, and only in appropriate event
5115 handler call).
5116 |<br>
5117 You cannot use it to set or remove a selection in a multiple-selection
5118 list box, so you should set option loNoExtendSel to true.
5119 |<br>
5120 In OnClick event handler, CurIndex has not yet changed. Use OnSelChange
5121 to respond to selection changes. }
5123 property Count: Integer read GetItemsCount write SetItemsCount;
5124 {* |<#listbox>
5125 |<#combo>
5126 |<#listview>
5127 |<#treeview>
5128 |<#edit>
5129 |<#memo>
5130 |<#richedit>
5131 |<#toolbar>
5132 Number of items (listbox, combobox, listview) or lines (multiline
5133 editbox, richedit control) or buttons (toolbar). It is possible to
5134 assign a value to this property only for listbox control with loNoData
5135 style and for list view control with lvoOwnerData style (virtual list
5136 box and list view). }
5138 property Items[ Idx: Integer ]: String read GetItems write SetItems;
5139 {* |<#edit>
5140 |<#listbox>
5141 |<#combo>
5142 |<#memo>
5143 |<#richedit>
5144 Obvious. Used with editboxes, listbox, combobox. With list view, use
5145 property LVItems instead. }
5147 function Item2Pos( ItemIdx: Integer ): Integer;
5148 {* |<#edit>
5149 |<#memo>
5150 Only for edit controls: converts line index to character position. }
5151 function Pos2Item( Pos: Integer ): Integer;
5152 {* |<#edit>
5153 |<#memo>
5154 Only for edit controls: converts character position to line index. }
5156 function EditTabChar: PControl;
5157 {* |<#edit>
5158 |<#memo>
5159 Call this method (once) to provide insertion of tab character (code #9)
5160 when tab key is pressed on keyboard. }
5162 function IndexOf( const S: String ): Integer;
5163 {* |<#listbox>
5164 |<#combobox>
5165 |<#tabcontrol>
5166 Works for the most of control types, though some of those
5167 have its own methods to search given item. If a control is not
5168 list box or combobox, item is finding by enumerating all
5169 the Items one by one. See also SearchFor method. }
5170 function SearchFor( const S: String; StartAfter: Integer; Partial: Boolean ): Integer;
5171 {* |<#listbox>
5172 |<#combobox>
5173 |<#tabcontrol>
5174 Works for the most of control types, though some of those
5175 have its own methods to search given item. If a control is not
5176 list box or combobox, item is finding by enumerating all
5177 the Items one by one. See also IndexOf method. }
5180 property ItemSelected[ ItemIdx: Integer ]: Boolean read GetItemSelected write SetItemSelected;
5181 {* |<#edit>
5182 |<#memo>
5183 |<#listbox>
5184 |<#combo>
5185 Returns True, if a line (in editbox) or an item (in listbox, combobox) is
5186 selected.
5187 Can be set only for listboxes. For listboxes, which are not multiselect, and
5188 for combo lists, it is possible only to set to True, to change selection. }
5190 property ItemData[ Idx: Integer ]: DWORD read GetItemData write SetItemData;
5191 {* |<#listbox>
5192 |<#combo>
5193 Access to user-defined data, associated with the item of a list box and
5194 combo box. }
5195 property OnDropDown: TOnEvent read fOnDropDown write fOnDropDown;
5196 {* |<#combo>
5197 |<#toolbar>
5198 Is called when combobox is dropped down (or drop-down button of
5199 toolbar is pressed - see also OnTBDropDown). }
5200 property OnCloseUp: TOnEvent read fOnCloseUp write fOnCloseUp;
5201 {* |<#combo>
5202 Is called when combobox is closed up. When drop down list is closed
5203 because user pressed "Escape" key, previous selection is restored.
5204 To test if it is so, call GetKeyState( VK_ESCAPE ) and check, if
5205 negative value is returned (i.e. Escape key is pressed when event
5206 handler is calling). }
5207 property DroppedWidth: Integer read FDroppedWidth write SetDroppedWidth;
5208 {* |<#combo>
5209 Allows to change width of dropped down items list for combobox (only!)
5210 control. }
5211 property DroppedDown: Boolean read fDropped write SetDroppedDown;
5212 {* |<#combo>
5213 Dropped down state for combo box. Set it to TRUE or FALSE to change
5214 dropped down state. }
5215 procedure AddDirList( const Filemask: String; Attrs: DWORD );
5216 {* |<#listbox>
5217 |<#combo>
5218 Can be used only with listbox and combobox - to add directory list items,
5219 filtered by given Filemask (can contain wildcards) and Attrs. Following
5220 flags can be combined in Attrs:
5221 |<table border=0>
5222 |&L=<tr><td>%1</td><td>
5223 <L DDL_ARCHIVE> Include archived files. <E>
5224 <L DDL_DIRECTORY> Includes subdirectories. Subdirectory names are
5225 enclosed in square brackets ([ ]). <E>
5226 <L DDL_DRIVES> Includes drives. Drives are listed in the form [-x-],
5227 where x is the drive letter. <E>
5228 <L DDL_EXCLUSIVE> Includes only files with the specified attributes.
5229 By default, read-write files are listed even if DDL_READWRITE is
5230 not specified. Also, this flag needed to list directories only,
5231 etc. <E>
5232 <L DDL_HIDDEN> Includes hidden files. <E>
5233 <L DDL_READONLY> Includes read-only files. <E>
5234 <L DDL_READWRITE> Includes read-write files with no additional
5235 attributes. <E>
5236 <L DDL_SYSTEM> Includes system files. <E>
5237 </table>
5238 If the listbox is sorted, directory items will be sorted (alpabetically). }
5239 property OnBitBtnDraw: TOnBitBtnDraw read fOnBitBtnDraw write fOnBitBtnDraw;
5240 {* |<#bitbtn>
5241 Special event for BitBtn. Using it, it is possible to provide
5242 additional effects, such as highlighting button text (by changing
5243 its Font and other properties). If the handler returns True, it is
5244 supposed that it made all drawing and there are no further drawing
5245 occure. }
5246 property BitBtnDrawMnemonic: Boolean read FBitBtnDrawMnemonic write SetBitBtnDrawMnemonic;
5247 {* |<#bitbtn>
5248 Set this property to TRUE to provide correct drawing of bit btn control
5249 caption with '&' characters (to remove such characters, and underline
5250 follow ones). }
5251 property TextShiftX: Integer read fTextShiftX write fTextShiftX;
5252 {* |<#bitbtn>
5253 Horizontal shift for bitbtn text when the bitbtn is pressed. }
5254 property TextShiftY: Integer read fTextShiftY write fTextShiftY;
5255 {* |<#bitbtn>
5256 Vertical shift for bitbtn text when the bitbtn is pressed. }
5257 property BitBtnImgIdx: Integer read GetBitBtnImgIdx write SetBitBtnImgIdx;
5258 {* |<#bitbtn>
5259 BitBtn image index for the first image in list view, used as bitbtn
5260 image. It is used only in case when BitBtn is created with bboImageList
5261 option. }
5262 property BitBtnImgList: THandle read GetBitBtnImageList write SetBitBtnImageList;
5263 {* |<#bitbtn>
5264 BitBtn Image list. Assign image list handle to change it. }
5266 function SetButtonIcon( aIcon: HIcon ): PControl;
5267 {* |<#button>
5268 Sets up button icon image and changes its styles. Returns button itself. }
5269 function SetButtonBitmap( aBmp: HBitmap ): PControl;
5270 {* |<#button>
5271 Sets up button icon image and changes its styles. Returns button itself. }
5273 property OnMeasureItem: TOnMeasureItem read fOnMeasureItem write SetOnMeasureItem;
5274 {* |<#combo>
5275 |<#listbox>
5276 |<#listview>
5277 This event is called for owner-drawn controls, such as list box, combo box,
5278 list view with appropriate owner-drawn style. For fixed item height controls
5279 (list box with loOwnerDrawFixed style, combobox with coOwnerDrawFixed and
5280 list view with lvoOwnerDrawFixed option) this event is called once. For
5281 list box with loOwnerDrawVariable style and for combobox with coOwnerDrawVariable
5282 style this event is called for every item. }
5284 property DefaultBtn: Boolean index 13
5285 {$IFDEF F_P} read GetDefaultBtn
5286 {$ELSE DELPHI} read fDefaultBtn
5287 {$ENDIF F_P/DELPHI} write SetDefaultBtn;
5288 {* |<#button>
5289 |<#bitbtn>
5290 Set this property to true to make control clicked when ENTER key is pressed.
5291 This property uses OnMessage event of the parent form, storing it into
5292 fOldOnMessage field and calling in chain. So, assign default button
5293 after setting OnMessage event for the form. }
5294 property CancelBtn: Boolean index 27
5295 {$IFDEF F_P} read GetDefaultBtn
5296 {$ELSE DELPHI} read fCancelBtn
5297 {$ENDIF F_P/DELPHI} write SetDefaultBtn;
5298 {* |<#button>
5299 |<#bitbtn>
5300 Set this property to true to make control clicked when escape key is pressed.
5301 This property uses OnMessage event of the parent form, storing it into
5302 fOldOnMessage field and calling in chain. So, assign cancel button
5303 after setting OnMessage event for the form. }
5304 function AllBtnReturnClick: PControl;
5305 {* Call this method for a form or any its control to provide clicking
5306 a focused button when ENTER pressed. By default, a button can be clicked
5307 only by SPACE key from the keyboard, or by mouse. }
5308 property IgnoreDefault: Boolean read fIgnoreDefault write fIgnoreDefault;
5309 {* Change this property to TRUE to ignore default button reaction on
5310 press ENTER key when a focus is grabbed of the control. Default
5311 value is different for different controls. By default, DefaultBtn
5312 ignored in memo, richedit (even if read-only). }
5315 property Color: TColor read fColor write SetCtlColor;
5316 {* Property Color is one of the most common for all visual
5317 elements (like form, control etc.) Please note, that standard GUI button
5318 can not change its color and the most characteristics of the Font. Also,
5319 standard button can not become Transparent. Use bitbtn for such purposes.
5320 Also, changing Color property for some kinds of control has no effect (rich edit,
5321 list view, tree view, etc.). To solve this, use native (for such controls)
5322 color property, or call Perform method with appropriate message to set the
5323 background color. }
5324 property Font: PGraphicTool read GetFont;
5325 {* If the Font property is not accessed, correspondent TGraphicTool object
5326 is not created and its methods are not included into executable. Leaving
5327 properties Font and Brush untouched can economy executable size a lot. }
5328 property Brush: PGraphicTool read GetBrush;
5329 {* If not accessed, correspondent TGraphicTool object is not created
5330 and its methods are not referenced. See also note on Font property. }
5332 property Ctl3D: Boolean read fCtl3D write SetCtl3D;
5333 {* Inheritable from parent controls to child ones. }
5335 procedure Show;
5336 {* |<#appbutton>
5337 |<#form>
5338 Makes control visible and activates it. }
5339 function ShowModal: Integer;
5340 {* |<#form>
5341 Can be used only with a forms to show it modal. See also global function
5342 ShowMsgModal.
5343 |<br>
5344 To use a form as a modal, it is possible to make it either auto-created
5345 or dynamically created. For a first case, You (may be prefer to hide a
5346 form after showing it as a modal:
5348 ! procedure TForm1.Button1Click( Sender: PObj );
5349 ! begin
5350 ! Form2.Form.ShowModal;
5351 ! Form2.Form.Hide;
5352 ! end;
5354 Another way is to create modal form just before showing it (this economies
5355 system resources):
5357 ! procedure TForm1.Button1Click( Sender: PObj );
5358 ! begin
5359 ! NewForm2( Form2, Applet );
5360 ! Form2.Form.ShowModal;
5361 ! Form2.Form.Free; // Never call Form2.Free or Form2.Form.Close
5362 ! end; // but always Form2.Form.Free; (!)
5364 In samples above, You certainly can place any wished code before and after
5365 calling ShowModal method.
5366 |<br>
5367 Do not forget that if You have more than a single form in your project,
5368 separate Applet object should be used.
5369 |<br>
5370 See also ShowModalEx.
5372 function ShowModalParented( const AParent: PControl ): Integer;
5373 {* by Alexander Pravdin. The same as ShowModal, but with a certain
5374 form as a parent. }
5375 function ShowModalEx: Integer;
5376 {* The same as ShowModal, but all the windows of current thread are
5377 disabled while showing form modal. This is useful if KOL form from
5378 a DLL is used modally in non-KOL application. }
5379 property ModalResult: Integer read fModalResult write
5380 {$IFDEF USE_SETMODALRESULT}
5381 SetModalResult;
5382 {$ELSE}
5383 fModalResult;
5384 {$ENDIF}
5385 {* |<#form>
5386 Modal result. Set it to value<>0 to stop modal dialog. By agreement,
5387 value 1 corresponds 'OK', 2 - 'Cancel'. But it is totally by decision
5388 of yours how to interpret this value. }
5389 property Modal: Boolean read GetModal;
5390 {* |<#form>
5391 TRUE, if the form is shown modal. }
5392 property ModalForm: PControl read fModalForm write fModalForm;
5393 {* |<#form>
5394 |<#appbutton>
5395 Form currently shown modal from this form or from Applet. }
5397 procedure Hide;
5398 {* |<#appbutton>
5399 |<#form>
5400 Makes control hidden. }
5401 property OnShow: TOnEvent read FOnShow write SetOnShow;
5402 {* Is called when a control or form is to be shown. This event is not fired
5403 for a form, if its WindowState initially is set to wsMaximized or
5404 wsMinimized. This behaviour is by design (the window does not receive
5405 WM_SHOW message in such case). }
5406 property OnHide: TOnEvent read FOnHide write SetOnHide;
5407 {* Is called when a control or form becomes hidden. }
5408 property WindowState: TWindowState read GetWindowState write SetWindowState;
5409 {* |<#form>
5410 Window state. }
5412 property Canvas: PCanvas read GetCanvas;
5413 {* |<#paintbox>
5414 Placeholder for Canvas: PCanvas. But in KOL, it is possible to
5415 create applets without canvases at all. To do so, avoid using
5416 Canvas and use DC directly (which is passed in OnPaint event). }
5417 function CallDefWndProc( var Msg: TMsg ): Integer;
5418 {* Function to be called in WndProc method to redirect message handling
5419 to default window procedure. }
5420 function DoSetFocus: Boolean;
5421 {* Sets focus for Enabled window. Returns True, if success. }
5423 procedure MinimizeNormalAnimated;
5424 {* |<#form>
5425 Apply this method to a main form (not to another form or Applet,
5426 even when separate Applet control is not used and main form matches it!).
5427 This provides normal animated visual minimization for the application.
5428 It therefore has no effect, if animation during minimize/resore is
5429 turned off by user. }
5431 property OnMessage: TOnMessage read fOnMessage write fOnMessage;
5432 {* |<#appbutton>
5433 |<#form>
5434 Is called for every message processed by TControl object. And for
5435 Applet window, this event is called also for all messages, handled by
5436 all its child windows (forms). }
5438 function IsMainWindow: Boolean;
5439 {* |<#appbutton>
5440 |<#form>
5441 Returns True, if a window is the main in application (created first
5442 after the Applet, or matches the Applet). }
5443 property IsApplet: Boolean read FIsApplet;
5444 {* Returns true, if the control is created using NewApplet (or CreateApplet).
5446 property IsForm: Boolean read fIsForm;
5447 {* Returns True, if the object is form window. }
5448 property IsMDIChild: Boolean read fIsMDIChild;
5449 {* Returns TRUE, if the object is MDI child form. In such case, IsForm also
5450 returns TRUE. }
5451 property IsControl: Boolean read fIsControl;
5452 {* Returns True, is the control is control (not form or applet). }
5453 property IsButton: Boolean read fIsButton;
5454 {* Returns True, if the control is button-like or containing buttons (button,
5455 bitbtn, checkbox, radiobox, toolbar). }
5457 function ProcessMessage: Boolean;
5458 {* |<#appbutton>
5459 Processes one message. See also ProcessMessages. }
5461 procedure ProcessMessages;
5462 {* |<#appbutton>
5463 Processes pending messages during long cycle of calculation,
5464 allowing to window to be repainted if needed and to respond to other
5465 messages. But if there are no such messages, your application can be
5466 stopped until such one appear in messages queue. To prevent such
5467 situation, use method ProcessPendingMessages instead. }
5469 procedure ProcessMessagesEx;
5470 {* Version of ProcessMessages, which works always correctly, even if
5471 the application is minimized or background. }
5473 procedure ProcessPendingMessages;
5474 {* |<#appbutton>
5475 Similar to ProcessMessages, but without waiting of
5476 message in messages queue. I.e., if there are no pending
5477 messages, this method immediately returns control to your
5478 code. This method is better to call during long cycle of
5479 calculation (then ProcessMessages). }
5480 procedure ProcessPaintMessages;
5481 {* }
5482 function WndProc( var Msg: TMsg ): Integer; virtual;
5483 {* Responds to all Windows messages, posted (sended) to the
5484 window, before all other proceeding. You can override it in
5485 derived controls, but in KOL there are several other ways
5486 to control message flow of existing controls without deriving
5487 another costom controls for only such purposes. See OnMessage,
5488 AttachProc. }
5489 property HasBorder: Boolean read GetHasBorder write SetHasBorder;
5490 {* |<#form>
5491 Obvious. Form-aware. }
5493 property HasCaption: Boolean read GetHasCaption write SetHasCaption;
5494 {* |<#form>
5495 Obvious. Form-aware. }
5496 property CanResize: Boolean read GetCanResize write SetCanResize;
5497 {* |<#form>
5498 Obvious. Form-aware. }
5499 property StayOnTop: Boolean read GetStayOnTop write SetStayOnTop;
5500 {* |<#form>
5501 Obvious. Form-aware, but can be applied to controls. }
5502 property Border: Integer read fMargin write fMargin;
5503 {* |<#form>
5504 Distance between edges and child controls and between child
5505 controls by default (if methods PlaceRight, PlaceDown, PlaceUnder,
5506 ResizeParent, ResizeParentRight, ResizeParentBottom are called).
5507 |<br>
5508 Originally was named Margin, now I recommend to use the name 'Border' to
5509 avoid confusion with MarginTop, MarginBottom, MarginLeft and
5510 MarginRight properties.
5511 |<br>
5512 Initial value is always 2. Border property is used in realigning
5513 child controls (when its Align property is not caNone), and value
5514 of this property determines size of borders between edges of children
5515 and its parent and between aligned controls too.
5516 |<br>
5517 See also properties MarginLeft, MarginRight, MarginTop, MarginBottom. }
5518 function SetBorder( Value: Integer ): PControl;
5519 {* Assigns new Border value, and returns @ Self. }
5521 property Margin: Integer read fMargin write fMargin;
5522 {* |<#form>
5523 Old name for property Border. }
5525 property MarginTop: Integer index 1
5526 {$IFDEF F_P} read GetClientMargin
5527 {$ELSE DELPHI} read fClientTop
5528 {$ENDIF F_P/DELPHI} write SetClientMargin;
5529 {* Additional distance between true window client top and logical top of
5530 client rectangle. This value is added to Top of rectangle, returning
5531 by property ClientRect. Together with other margins and property Border,
5532 this property allows to change view of form for case, that Align property
5533 is used to align controls on parent (it is possible to provide some
5534 distance from child controls to its parent, and between child controls.
5535 |<br>
5536 Originally this property was introduced to compensate incorrect
5537 ClientRect property, calculated for some types of controls.
5538 |<br>
5539 See also properties Border, MarginBottom, MarginLeft, MarginRight. }
5540 property MarginBottom: Integer index 2
5541 {$IFDEF F_P} read GetClientMargin
5542 {$ELSE DELPHI} read fClientBottom
5543 {$ENDIF F_P/DELPHI} write SetClientMargin;
5544 {* The same as MarginTop, but a distance between true window Bottom of
5545 client rectangle and logical bottom one. Take in attention, that this value
5546 should be POSITIVE to make logical bottom edge located above true edge.
5547 |<br>
5548 See also properties Border, MarginTop, MarginLeft, MarginRight. }
5549 property MarginLeft: Integer index 3
5550 {$IFDEF F_P} read GetClientMargin
5551 {$ELSE DELPHI} read fClientLeft
5552 {$ENDIF F_P/DELPHI} write SetClientMargin;
5553 {* The same as MarginTop, but a distance between true window Left of
5554 client rectangle and logical left edge.
5555 |<br>
5556 See also properties Border, MarginTop, MarginRight, MarginBottom. }
5557 property MarginRight: Integer index 4
5558 {$IFDEF F_P} read GetClientMargin
5559 {$ELSE DELPHI} read fClientRight
5560 {$ENDIF F_P/DELPHI} write SetClientMargin;
5561 {* The same as MarginLeft, but a distance between true window Right of
5562 client rectangle and logical bottom one. Take in attention, that this value
5563 should be POSITIVE to make logical right edge located left of true edge.
5564 |<br>
5565 See also properties Border, MarginTop, MarginLeft, MarginBottom. }
5567 property Tabstop: Boolean read fTabstop write fTabstop;
5568 {* True, if control can be focused using tabulating between controls.
5569 Set it to False to make control unavailable for keyboard, but only
5570 for mouse. }
5572 property TabOrder: Integer read fTabOrder write SetTabOrder;
5573 {* Order of tabulating of controls. Initially, TabOrder is equal to
5574 creation order of controls. If TabOrder changed, TabOrder of
5575 all controls with not less value of one is shifted up. To place
5576 control before another, assign TabOrder of one to another.
5577 For example:
5578 ! Button1.TabOrder := EditBox1.TabOrder;
5579 In code above, Button1 is placed just before EditBox1 in tabulating
5580 order (value of TabOrder of EditBox1 is incremented, as well as
5581 for all follow controls). }
5583 property Focused: Boolean read GetFocused write SetFocused;
5584 {* True, if the control is current on form (but check also, what form
5585 itself is focused). For form it is True, if the form is active (i.e.
5586 it is foreground and capture keyboard). Set this value to True to make
5587 control current and focused (if applicable). }
5589 function BringToFront: PControl;
5590 {* Changes z-order of the control, bringing it to the topmost level. }
5591 function SendToBack: PControl;
5592 {* Changes z-order of the control, sending it to the back of siblings. }
5593 property TextAlign: TTextAlign read GetTextAlign write SetTextAlign;
5594 {* |<#label>
5595 |<#panel>
5596 |<#button>
5597 |<#bitbtn>
5598 |<#edit>
5599 |<#memo>
5600 Text horizontal alignment. Applicable to labels, buttons,
5601 multi-line edit boxes, panels. }
5602 property VerticalAlign: TVerticalAlign read GetVerticalAlign write SetVerticalAlign;
5603 {* |<#button>
5604 |<#label>
5605 |<#panel>
5606 Text vertical alignment. Applicable to buttons, labels and panels. }
5607 property WordWrap: Boolean read fWordWrap;
5608 {* TRUE, if this is a label, created using NewWordWrapLabel. }
5609 property ShadowDeep: Integer read FShadowDeep write SetShadowDeep;
5610 {* |<#3dlabel>
5611 Deep of a shadow (for label effect only, created calling NewLabelEffect). }
5613 property CannotDoubleBuf: Boolean read fCannotDoubleBuf write fCannotDoubleBuf;
5614 {* }
5615 property DoubleBuffered: Boolean read fDoubleBuffered write SetDoubleBuffered;
5616 {* Set it to true for some controls, which are flickering in repainting
5617 (like label effect). Slow, and requires additional code. This property
5618 is inherited by all child controls.
5619 |<br>&nbsp;&nbsp;&nbsp;
5620 Note: RichEdit control can not become DoubleBuffered. }
5621 //function IsSelfOrParentDblBuf: Boolean;
5622 {* Returns true, if DoubleBuffered or one of parents is DoubleBuffered. }
5623 function DblBufTopParent: PControl;
5624 {* Returns the topmost DoubleBuffered Parent control. }
5625 property Transparent: Boolean read fTransparent write SetTransparent;
5626 {* Set it to true to get special effects. Transparency also uses
5627 DoubleBuffered and inherited by child controls.
5628 |<br>&nbsp;&nbsp;&nbsp;
5629 Please note, that some controls can not be shown properly, when
5630 Transparent is set to True for it. If You want to make edit control
5631 transparent (e.g., over gradient filled panel), handle its OnChanged
5632 property and call there Invalidate to provide repainting of edit
5633 control content. Note also, that for RichEdit control property
5634 Transparent has no effect (as well as DoubleBuffered). But special
5635 property RE_Transparent is designed especially for RichEdit control
5636 (it works fine, but with great number of flicks while resizing
5637 of a control). Another note is about Edit control. To allow editing
5638 of transparent edit box, it is necessary to invalidate it for
5639 every pressed character. Or, use Ed_Transparent property instead. }
5641 property Ed_Transparent: Boolean read fTransparent write EdSetTransparent;
5642 {* |<#edit>
5643 |<#memo>
5644 Use this property for editbox to make it really Transparent. Remember,
5645 that though Transparent property is inherited by child controls from
5646 its parent, this is not so for Ed_Transparent. So, it is necessary to
5647 set Ed_Transparent to True for every edit control explicitly. }
5648 property AlphaBlend: Integer read fAlphaBlend write SetAlphaBlend;
5649 {* |<#form>
5650 If assigned to 0..254, makes window (form or control) semi-transparent
5651 (Win2K only).
5652 |<br>
5653 Depending on value assigned, it is possible to adjust transparency
5654 level ( 0 - totally transparent, 255 - totally opaque). }
5656 property LookTabKeys: TTabKeys read fLookTabKeys write fLookTabKeys;
5657 {* Set of keys which can be used as tabulation keys in a control. }
5658 procedure GotoControl( Key: DWORD );
5659 {* |<#form>
5660 Emulates tabulation key press w/o sending message to current control.
5661 Can be applied to a form or to any its control. If VK_TAB is used,
5662 state of shift kay is checked in: if it is pressed, tabulate is in
5663 backward direction. }
5664 property SubClassName: String read get_ClassName write set_ClassName;
5665 {* Name of window class - unique for every window class
5666 in every run session of a program. }
5668 property OnClose: TOnEventAccept read fOnClose write fOnClose;
5669 {* |<#form>
5670 |<#applet>
5671 Called before closing the window. It is possible to set Accept
5672 parameter to False to prevent closing the window. This event events
5673 is not called when windows session is finishing (to handle this
5674 event, handle WM_QUERYENDSESSION message, or assign OnQueryEndSession
5675 event to another or the same event handler). }
5677 property OnQueryEndSession: TOnEventAccept read fOnQueryEndSession write SetOnQueryEndSession;
5678 {* |<#form>
5679 |<#applet>
5680 Called when WM_QUERYENDSESSION message come in. It is possible to set Accept
5681 parameter to False to prevent closing the window (in such case session ending
5682 is halted). It is possible to check CloseQueryReason property to find out,
5683 why event occur. }
5684 property CloseQueryReason: TCloseQueryReason read fCloseQueryReason;
5685 {* Reason why OnClose or OnQueryEndSession called. }
5686 property OnMinimize: TOnEvent index 0
5687 {$IFDEF F_P} read GetOnMinMaxRestore
5688 {$ELSE DELPHI} read fOnMinimize
5689 {$ENDIF F_P/DELPHI} write SetOnMinMaxRestore;
5690 {* |<#form>
5691 Called when window is minimized. }
5692 property OnMaximize: TOnEvent index 8
5693 {$IFDEF F_P} read GetOnMinMaxRestore
5694 {$ELSE DELPHI} read fOnMaximize
5695 {$ENDIF F_P/DELPHI} write SetOnMinMaxRestore;
5696 {* |<#form>
5697 Called when window is maximized. }
5698 property OnRestore: TOnEvent index 16
5699 {$IFDEF F_P} read GetOnMinMaxRestore
5700 {$ELSE DELPHI} read fOnRestore
5701 {$ENDIF F_P/DELPHI} write SetOnMinMaxRestore;
5702 {* |<#form>
5703 Called when window is restored from minimized or maximized state. }
5705 property UpdateRgn: HRgn read fUpdRgn;
5706 {* A handle of update region. Valid only in OnPaint method. You
5707 can use it to improve painting (for speed), if necessary. When
5708 UpdateRgn is obtained in response to WM_PAINT message, value
5709 of the property EraseBackground is used to pass it to the API
5710 function GetUpdateRgn. If UpdateRgn = 0, this means that entire
5711 window should be repainted. Otherwise, You (e.g.) can check
5712 if the rectangle is in clipping region using API function
5713 RectInRegion. }
5715 property EraseBackground: Boolean read fEraseUpdRgn write fEraseUpdRgn;
5716 {* This value is used to pass it to the API function GetUpdateRgn,
5717 when UpadateRgn property is obtained first in responce to WM_PAINT
5718 message. If EraseBackground is set to True, system is responsible
5719 for erasing background of update region before painting. If not
5720 (default), the entire region invalidated should be painted by your
5721 event handler. }
5723 property OnPaint: TOnPaint read fOnPaint write SetOnPaint;
5724 {* Event to set to override standard control painting. Can be applied
5725 to any control (though originally was designed only for paintbox
5726 control). When an event handler is called, it is possible to use
5727 UpdateRgn to examine what parts of window require painting to
5728 improve performance of the painting operation. }
5731 property OnEraseBkgnd: TOnPaint read fOnEraseBkgnd write SetOnEraseBkgnd;
5732 {* This event allows to override erasing window background in response
5733 to WM_ERASEBKGND message. This allows to add some decorations to
5734 standard controls without overriding its painting in total.
5735 Note: When erase background, remember, that property ClientRect can
5736 return not true client rectangle of the window - use GetClientRect
5737 API function instead. For example:
5739 !var BkBmp: HBitmap;
5741 !procedure TForm1.KOLForm1FormCreate(Sender: PObj);
5742 !begin
5743 ! Toolbar1.OnEraseBkgnd := DecorateToolbar;
5744 ! BkBmp := LoadBitmap( hInstance, 'BK1' );
5745 !end;
5747 !procedure TForm1.DecorateToolbar(Sender: PControl; DC: HDC);
5748 !var CR: TRect;
5749 !begin
5750 ! GetClientRect( Sender.Handle, CR );
5751 ! Sender.Canvas.Brush.BrushBitmap := BkBmp;
5752 ! Sender.Canvas.FillRect( CR );
5753 !end;
5758 property OnClick: TOnEvent read fOnClick write fOnClick;
5759 {* |<#button>
5760 |<#checkbox>
5761 |<#radiobox>
5762 |<#toolbar>
5763 Called on click at control. For buttons, checkboxes and radioboxes
5764 is called regadless if control clicked by mouse or keyboard. For toolbar,
5765 the same event is used for all toolbar buttons and toolbar itself.
5766 To determine which toolbar button is clicked, check CurIndex property.
5767 And note, that all the buttons including separator buttons are enumerated
5768 starting from 0. Though images are stored (and prepared) only for
5769 non-separator buttons. And to determine, if toolbar button was clicked
5770 with right mouse button, check RightClick property. }
5771 property RightClick: Boolean read fRightClick;
5772 {* |<#toolbar>
5773 |<#listview>
5774 Use this property to determine which mouse button was clicked
5775 (applicable to toolbar in the OnClick event handler). }
5776 property OnEnter: TOnEvent read fOnEnter write fOnEnter;
5777 {* Called when control receives focus. }
5778 property OnLeave: TOnEvent read fOnLeave write fOnLeave;
5779 {* Called when control looses focus. }
5780 property OnChange: TOnEvent read fOnChange write fOnChange;
5781 {* |<#edit>
5782 |<#memo>
5783 |<#listbox>
5784 |<#combo>
5785 |<#tabcontrol>
5786 Called when edit control is changed, or selection in listbox or
5787 current index in combobox is changed (but if OnSelChanged assigned,
5788 the last is called for change selection). To respond to check/uncheck
5789 checkbox or radiobox events, use OnClick instead. }
5790 property OnSelChange: TOnEvent read fOnSelChange write fOnSelChange;
5791 {* |<#richedit>
5792 |<#listbox>
5793 |<#combo>
5794 |<#treeview>
5795 Called for rich edit control, listbox, combobox or treeview when current selection
5796 (range, or current item) is changed. If not assigned, but OnChange is
5797 assigned, OnChange is called instead. }
5798 property OnResize: TOnEvent read FOnResize write SetOnResize;
5799 {* Called whenever control receives message WM_SIZE (thus is, if
5800 control is resized. }
5801 property OnMove: TOnEvent read FOnMove write SetOnMove;
5802 {* Called whenever control receives message WM_MOVE (i.e. when control is
5803 moved over its parent). }
5805 property MinSizePrev: Integer read fSplitMinSize1 write fSplitMinSize1;
5806 {* |<#splitter>
5807 Minimal allowed (while dragging splitter) size of previous control
5808 for splitter (see NewSplitter). }
5809 property SplitMinSize1: Integer read fSplitMinSize1 write fSplitMinSize1;
5810 {* The same as MinSizePrev. }
5811 property MinSizeNext: Integer read fSplitMinSize2 write fSplitMinSize2;
5812 {* |<#splitter>
5813 Minimal allowed (while dragging splitter) size of the rest of parent
5814 of splitter or of SecondControl (see NewSplitter). }
5815 property SplitMinSize2: Integer read fSplitMinSize2 write fSplitMinSize2;
5816 {* The same as MinSizeNext. }
5817 property SecondControl: PControl read fSecondControl write fSecondControl;
5818 {* |<#splitter>
5819 Second control to check (while dragging splitter) if its size not less
5820 than SplitMinSize2 (see NewSplitter). By default, second control is
5821 not necessary, and needed only in rare case when SecondControl can not
5822 be determined automatically to restrict splitter right (bottom) position. }
5823 property OnSplit: TOnSplit read fOnSplit write fOnSplit;
5824 {* |<#splitter>
5825 Called when splitter control is dragging - to allow for
5826 your event handler to decide if to accept new size of
5827 left (top) control, and new size of the rest area of parent. }
5828 property Dragging: Boolean read FDragging;
5829 {* |<#splitter>
5830 True, if splitter control is dragging now by user with left
5831 mouse button. Also, this property can be used to detect if the control
5832 is dragging with mouse (after calling DragStartEx method). }
5833 procedure DragStart;
5834 {* Call this method for a form or control to drag it with left mouse button,
5835 when mouse left button is already down. Dragging is stopped when left mouse
5836 button is released. See also DragStartEx, DragStopEx. }
5837 procedure DragStartEx;
5838 {* Call this method to start dragging the form by mouse. To stop
5839 dragging, call DragStopEx method. (Tip: to detect mouse up event,
5840 use OnMouseUp event of the dragging control). This method can be used
5841 to move any control with the mouse, not only entire form. State of
5842 mouse button is not significant. Determine dragging state of the control
5843 checking its Dragging property. }
5844 procedure DragStopEx;
5845 {* Call this method to stop dragging the form (started by DragStopEx). }
5846 procedure DragItem( OnDrag: TOnDrag );
5847 {* Starts dragging something with mouse. During the process,
5848 callback function OnDrag is called, which allows to control
5849 drop target, change cursor shape, etc. }
5851 property OnKeyDown: TOnKey read fOnKeyDown write SetOnKeyDown;
5852 {* Obvious. }
5853 property OnKeyUp: TOnKey read fOnKeyUp write SetOnKeyUp;
5854 {* Obvious. }
5855 property OnChar: TOnChar read fOnChar write SetOnChar;
5856 {* Obvious. }
5858 property OnMouseDown: TOnMouse read fOnMouseDown write SetMouseDown;
5859 {* Obvious. }
5860 property OnMouseUp: TOnMouse read fOnMouseUp write SetMouseUp;
5861 {* Obvious. }
5862 property OnMouseMove: TOnMouse read fOnMouseMove write SetMouseMove;
5863 {* Obvious. }
5864 property OnMouseDblClk: TOnMouse read fOnMouseDblClk write SetMouseDblClk;
5865 {* Obvious. }
5866 property OnMouseWheel: TOnMouse read fOnMouseWheel write SetMouseWheel;
5867 {* Obvious. }
5869 property OnMouseEnter: TOnEvent read fOnMouseEnter write SetOnMouseEnter;
5870 {* Is called when mouse is entered into control. See also OnMouseLeave. }
5871 property OnMouseLeave: TOnEvent read fOnMouseLeave write SetOnMouseLeave;
5872 {* Is called when mouse is leaved control. If this event is assigned,
5873 then mouse is captured on mouse enter event to handle all other
5874 mouse events until mouse cursor leaves the control. }
5875 property OnTestMouseOver: TOnTestMouseOver read fOnTestMouseOver write SetOnTestMouseOver;
5876 {* |<#bitbtn>
5877 Special event, which allows to extend OnMouseEnter / OnMouseLeave
5878 (and also Flat property for BitBtn control). If a handler is assigned
5879 to this event, actual testing whether mouse is in control or not,
5880 is occuring in the handler. So, it is possible to simulate more
5881 careful hot tracking for controls with non-rectangular shape (such
5882 as glyphed BitBtn control). }
5884 property MouseInControl: Boolean read fMouseInControl;
5885 {* |<#bitbtn>
5886 This property can return True only if OnMouseEnter / OnMouseLeave
5887 event handlers are set for a control (or, for BitBtn, property Flat
5888 is set to True. Otherwise, False is returned always. }
5890 property Flat: Boolean read fFlat write SetFlat;
5891 {* |<#bitbtn>
5892 Set it to True for BitBtn, to provide either flat border for a button
5893 or availability of "highlighting" (correspondent to glyph index 4).
5894 |<br>
5895 Note: this can work incorrectly a bit under win95 without comctl32.dll
5896 updated. Therefore, application will launch. To enforce correct working
5897 even under Win95, use your own timer, which event handler checks for
5898 mouse over bitbtn control, e.g.:
5899 ! procedure TForm1.Timer1Timer(Sender: PObj);
5900 ! var P: TPoint;
5901 ! begin
5902 ! if not BitBtn1.MouseInControl then Exit;
5903 ! GetCursorPos( P );
5904 ! P := BitBtn1.Screen2Client( P );
5905 ! if not PtInRect( BitBtn1.ClientRect, P ) then
5906 ! begin
5907 ! BitBtn1.Flat := FALSE;
5908 ! BitBtn1.Flat := TRUE;
5909 ! end;
5910 ! end;
5912 property RepeatInterval: Integer read fRepeatInterval write fRepeatInterval;
5913 {* |<#bitbtn>
5914 If this property is set to non-zero, it is interpreted (for BitBtn
5915 only) as an interval in milliseconds between repeat button down events,
5916 which are generated after first mouse or button click and until
5917 button is released. Though, if the button is pressed with keyboard (with
5918 space key), RepeatInterval value is ignored and frequency of repeatitive
5919 clicking is determined by user keyboard settings only. }
5920 function LikeSpeedButton: PControl;
5921 {* |<#button>
5922 |<#bitbtn>
5923 Transparent method (returns control itself). Makes button not focusable. }
5925 function Add( const S: String ): Integer;
5926 {* |<#listbox>
5927 |<#combo>
5928 Only for listbox and combobox. }
5930 function Insert( Idx: Integer; const S: String ): Integer;
5931 {* |<#listbox>
5932 |<#combo>
5933 Only for listbox and combobox. }
5934 procedure Delete( Idx: Integer );
5935 {* |<#listbox>
5936 |<#combo>
5937 Only for listbox and combobox. }
5938 procedure Clear;
5939 {* Clears object content. Has different sense for different controls.
5940 E.g., for label, editbox, button and other simple controls it
5941 assigns empty string to Caption property. For listbox, combobox,
5942 listview it deletes all items. For toolbar, it deletes all buttons.
5943 Et so on. }
5945 property Progress: Integer index ((PBM_SETPOS or $8000) shl 16) or PBM_GETPOS
5946 read GetIntVal write SetIntVal;
5947 {* |<#progressbar>
5948 Only for ProgressBar. }
5949 property MaxProgress: Integer index ((PBM_SETRANGE32 or $8000) shl 16) or PBM_GETRANGE
5950 read GetIntVal write SetMaxProgress;
5951 {* |<#progressbar>
5952 Only for ProgressBar. 100 is the default value. }
5953 property ProgressColor: TColor read fTextColor write SetProgressColor;
5954 {* |<#progressbar>
5955 Only for ProgressBar. }
5956 property ProgressBkColor: TColor read fColor write SetCtlColor; //SetProgressBkColor;
5957 {* |<#progressbar>
5958 Obsolete. Now the same as Color. }
5960 property StatusText[ Idx: Integer ]: PChar read GetStatusText write SetStatusText;
5961 {* |<#form>
5962 Only for forms to set/retrieve status text to/from given status panel.
5963 Panels are enumerated from 0 to 254, 255 is to indicate simple
5964 status bar. Size grip in right bottom corner of status window is
5965 displayed only if form still CanResize.
5966 |<br>
5967 When a status text is set first time, status bar window is created
5968 (always aligned to bottom), and form is resizing to preset client height.
5969 While status bar is showing, client height value is returned without
5970 height of status bar. To remove status bar, call RemoveStatus method for
5971 a form.
5972 |<br>
5973 By default, text is left-aligned within the specified part of a status
5974 window. You can embed tab characters (#9) in the text to center or
5975 right-align it. Text to the right of a single tab character is centered,
5976 and text to the right of a second tab character is right-aligned.
5977 |<br>
5978 If You use separate status bar onto several panels, these automatically
5979 align its widths to the same value (width divided to number of panels).
5980 To adjust status panel widths for every panel, use property StatusPanelRightX.
5982 property SimpleStatusText: PChar index 255 read GetStatusText write SetStatusText;
5983 {* |<#form>
5984 Only for forms to set/retrive status text to/from simple status bar.
5985 Size grip in right bottom corner of status window is displayed only
5986 if form CanResize.
5987 |<br>
5988 When status text set first time, (simple) status bar window is created
5989 (always aligned to bottom), and form is resizing to preset client height.
5990 While status bar is showing, client height value is returned without
5991 height of status bar. To remove status bar, call RemoveStatus method for
5992 a form.
5993 |<br>
5994 By default, text is left-aligned within the specified part of a status
5995 window. You can embed tab characters (#9) in the text to center or
5996 right-align it. Text to the right of a single tab character is centered,
5997 and text to the right of a second tab character is right-aligned.
5999 property StatusCtl: PControl read fStatusCtl;
6000 {* Pointer to Status bar control. To "create" child controls on
6001 the status bar, first create it as a child of form, for instance, and
6002 then change its property Parent, e.g.:
6003 ! var Progress1: PControl;
6004 ! ...
6005 ! Progress1 := NewProgressBar( Form1 );
6006 ! Progress1.Parent := Form1.StatusCtl;
6007 (If you use MCK, code should be another a bit, and in this case it is
6008 possible to create and adjust the control at design-time, and at run-time
6009 change its parent control. E.g. (Progress1 is created at run-time here too):
6010 ! Progress1 := NewProgressBar( Form );
6011 ! Progress1.Parent := Form.StatusCtl;
6013 Do not forget to provide StatusCtl to be existing first (e.g. assign
6014 one-space string to SimpleStatusText property of the form, for MCK do
6015 so using Object Inspector).
6017 property SizeGrip: Boolean read fSizeGrip write fSizeGrip;
6018 {* Size grip for status bar. Has effect only before creating window. }
6020 procedure RemoveStatus;
6021 {* |<#form>
6022 Call it to remove status bar from a form (created in result of assigning
6023 value(s) to StatusText[], SimpleStatusText properties). When status bar is
6024 removed, form is resized to preset client height. }
6025 function StatusPanelCount: Integer;
6026 {* |<#form>
6027 Returns number of status panels defined in status bar. }
6028 property StatusPanelRightX[ Idx: Integer ]: Integer read GetStatusPanelX write SetStatusPanelX;
6029 {* |<#form>
6030 Use this property to adjust status panel right edges (if the status bar is
6031 divided onto several subpanels). If the right edge for the last panel is
6032 set to -1 (by default) it is expanded to the right edge of a form window.
6033 Otherwise, status bar can be shorter then form width. }
6034 property StatusWindow: HWND read fStatusWnd;
6035 {* |<#form>
6036 Provided for case if You want to use API direct message sending to
6037 status bar. }
6039 property Color1: TColor read fColor1 write SetColor1;
6040 {* |<#gradient>
6041 Top line color for GradientPanel. }
6042 property Color2: TColor read fColor2 write SetColor2;
6043 {* |<#gradient>
6044 |<#3Dlabel>
6045 Bottom line color for GradientPanel, or shadow color for LabelEffect.
6046 (If clNone, shadow color for LabelEffect is calculated as a mix bitween
6047 TextColor and clBlack). }
6048 property GradientStyle: TGradientStyle read FGradientStyle write SetGradientStyle;
6049 {* |<#gradient>
6050 Styles other then gsVertical and gsHorizontal has effect only for
6051 gradient panel, created by NewGradientPanelEx. }
6052 property GradientLayout: TGradientLayout read FGradientLayout write SetGradientLayout;
6053 {* |<#gradient>
6054 Has only effect for gradient panel, created by NewGradientPanelEx.
6055 Ignored for styles gsVertical and gsHorizontal. }
6057 //======== Image lists (for ListView, TreeView, ToolBar and TabControl):
6058 property ImageListSmall: PImageList index 16 read GetImgListIdx write SetImgListIdx;
6059 {* |<#listview>
6060 Image list with small icons used with List View control. If not set,
6061 last added (i.e. created with a control as an owner) image list with
6062 small icons is used. }
6063 property ImageListNormal: PImageList index 32 read GetImgListIdx write SetImgListIdx;
6064 {* |<#listview>
6065 |<#treeview>
6066 |<#tabcontrol>
6067 |<#bitbtn>
6068 Image list with normal size icons used with List View control (or with
6069 icons for BitBtn, TreeView, ToolBar or TabControl). If not set,
6070 last added (i.e. created with a control as an owner) image list is used.
6072 property ImageListState: PImageList index 0 read GetImgListIdx write SetImgListIdx;
6073 {* |<#listview>
6074 |<#treeview>
6075 Image list used as a state images list for ListView or TreeView control. }
6077 //========
6078 function SetUnicode( Unicode: Boolean ): PControl;
6079 {* |<#listview>
6080 |<#treeview>
6081 |<#tabcontrol>
6082 Sets control as Unicode or not. The control itself is returned as for
6083 other "transparent" functions. A conditional define UNICODE_CTRLS must
6084 be added to a project to provide handling unicode messages. }
6086 //======== TabControl-specific properties and methods:
6087 property Pages[ Idx: Integer ]: PControl read GetPages;
6088 {* |<#tabcontrol>
6089 Returns controls, which can be used as parent for controls, placed on
6090 different pages of a tab control. Use it like in follows example:
6091 | Label1 := NewLabel( TabControl1.Pages[ 0 ], 'Label1' );
6092 To find number of pages available, check out Count property of the tab
6093 control. Pages are enumerated from 0 to Count - 1, as usual. }
6094 property TC_Pages[ Idx: Integer ]: PControl read GetPages;
6095 {* |<#tabcontrol>
6096 The same as above. }
6097 function TC_Insert( Idx: Integer; const TabText: String; TabImgIdx: Integer ): PControl;
6098 {* |<#tabcontrol>
6099 Inserts new tab before given, returns correspondent page control
6100 (which can be used as a parent for controls to place on the page). }
6101 procedure TC_Delete( Idx: Integer );
6102 {* |<#tabcontrol>
6103 Removes tab from tab control, destroying all its child controls. }
6104 property TC_Items[ Idx: Integer ]: String read TCGetItemText write TCSetItemText;
6105 {* |<#tabcontrol>
6106 Text, displayed on tab control tabs. }
6107 property TC_Images[ Idx: Integer ]: Integer read TCGetItemImgIDx write TCSetItemImgIdx;
6108 {* |<#tabcontrol>
6109 Image index for a tab in tab control. }
6110 property TC_ItemRect[ Idx: Integer ]: TRect read TCGetItemRect;
6111 {* |<#tabcontrol>
6112 Item rectangle for a tab in tab control. }
6113 procedure TC_SetPadding( cx, cy: Integer );
6114 {* |<#tabcontrol>
6115 Sets space padding around tab text in a tab of tab control. }
6116 function TC_TabAtPos( x, y: Integer ): Integer;
6117 {* |<#tabcontrol>
6118 Returns index of tab, found at the given position (relative to
6119 a client rectangle of tab control). If no tabs found at the
6120 position, -1 is returned. }
6121 function TC_DisplayRect: TRect;
6122 {* |<#tabcontrol>
6123 Returns rectangle, occupied by a page rather then tab. }
6124 function TC_IndexOf(const S: String): Integer;
6125 {* |<#tabcontrol>
6126 By Mr Brdo. Index of page by its Caption. }
6127 function TC_SearchFor(const S: String; StartAfter: Integer; Partial: Boolean): Integer;
6128 {* |<#tabcontrol>
6129 By Mr Brdo. Index of page by its Caption. }
6131 //======== ListView style and options:
6132 property LVStyle: TListViewStyle read fLVStyle write SetLVStyle;
6133 {* |<#listview>
6134 ListView style of view. Can be changed at run time. }
6136 property LVOptions: TListViewOptions read fLVOptions write SetLVOptions;
6137 {* |<#listview>
6138 ListView options. Can be changed at run time. }
6140 property LVTextColor: TColor index LVM_GETTEXTCOLOR
6141 {$IFDEF F_P} read LVGetColorByIdx
6142 {$ELSE DELPHI} read fTextColor
6143 {$ENDIF F_P/DELPHI} write LVSetColorByIdx;
6144 {* |<#listview>
6145 ListView text color. Use it instead of TextColor. }
6146 property LVTextBkColor: TColor index LVM_GETTEXTBKCOLOR
6147 {$IFDEF F_P} read LVGetColorByIdx
6148 {$ELSE DELPHI} read fLVTextBkColor
6149 {$ENDIF F_P/DELPHI} write LVSetColorByIdx;
6150 {* |<#listview>
6151 ListView background color for text. }
6152 property LVBkColor: TColor read fColor write SetCtlColor; //LVSetBkColor;
6153 {* |<#listview>
6154 ListView background color. Use it instead of Color. }
6156 //======== List View columns handling:
6157 property LVColCount: Integer read fLVColCount;
6158 {* |<#listview>
6159 ListView (additional) column count. Value 0 means that there are
6160 no columns (single item text / icon is used). If You want
6161 to provide several columns, first call LVColAdd to "insert" column 0,
6162 i.e. to provide header text for first column (with index 0).
6163 If there are no column, nothing will be shown in lvsDetail /
6164 lvsDetailNoHeader view style. }
6165 procedure LVColAdd( const aText: String; aalign: TTextAlign; aWidth: Integer );
6166 {* |<#listview>
6167 Adds new column. Pass 'width' <= 0 to provide default column width.
6168 'text' is a column header text. }
6169 {$IFNDEF _FPC}
6170 {$IFNDEF _D2}
6171 procedure LVColAddW( const aText: WideString; aalign: TTextAlign; aWidth: Integer );
6172 {* |<#listview>
6173 Adds new column (unicode version). }
6174 {$ENDIF _D2}
6175 {$ENDIF _FPC}
6176 procedure LVColInsert( ColIdx: Integer; const aText: String; aAlign: TTextAlign; aWidth: Integer );
6177 {* |<#listview>
6178 Inserts new column at the Idx position (1-based column index). }
6179 {$IFNDEF _FPC}
6180 {$IFNDEF _D2}
6181 procedure LVColInsertW( ColIdx: Integer; const aText: WideString; aAlign: TTextAlign; aWidth: Integer );
6182 {* |<#listview>
6183 Inserts new column at the Idx position (1-based column index). }
6184 {$ENDIF _D2}
6185 {$ENDIF _FPC}
6186 procedure LVColDelete( ColIdx: Integer );
6187 {* |<#listview>
6188 Deletes column from List View }
6189 property LVColWidth[ Item: Integer ]: Integer index LVM_GETCOLUMNWIDTH
6190 read GetItemVal write SetItemVal;
6191 {* |<#listview>
6192 Retrieves or changes column width. For lvsList view style, the same width
6193 is returned for all columns (ColIdx is ignored). It is possible to use
6194 special values to assign to a property:
6195 |<br> LVSCW_AUTOSIZE - Automatically sizes the column
6196 |<br> LVSCW_AUTOSIZE_USEHEADER - Automatically sizes the column to fit
6197 the header text
6198 |<br>
6199 To set coumn width in lvsList view mode, column index must be -1
6200 (and Width to set must be in range 0..32767 always). }
6201 property LVColText[ Idx: Integer ]: String read GetLVColText write SetLVColText;
6202 {* |<#listview>
6203 Allows to get/change column header text at run time. }
6204 {$IFNDEF _FPC}
6205 {$IFNDEF _D2}
6206 property LVColTextW[ Idx: Integer ]: WideString read GetLVColTextW write SetLVColTextW;
6207 {* |<#listview>
6208 Allows to get/change column header text at run time. }
6209 {$ENDIF _D2}
6210 {$ENDIF _FPC}
6211 property LVColAlign[ Idx: Integer ]: TTextAlign read GetLVColalign write SetLVColalign;
6212 {* |<#listview>
6213 Column text aligning. }
6214 property LVColImage[ Idx: Integer ]: Integer index LVCF_IMAGE or (24 shl 16) read GetLVColEx write SetLVColEx;
6215 {* |<#listview>
6216 Only starting from comctrl32.dll of version 4.70 (IE4+). Allows to
6217 set an image for list view column itself from the ImageListSmall.
6219 property LVColOrder[ Idx: Integer ]: Integer index LVCF_ORDER or (28 shl 16) read GetLVColEx write SetLVColEx;
6220 {* |<#listview>
6221 Only starting from comctrl32.dll of version 4.70 (IE4+). Allows to
6222 set visual order of the list view column from the ImageListSmall.
6223 This value does not affect the index, by which the column is still
6224 accessible in the column array.
6227 //======== List View items handling:
6228 property LVCount: Integer read GetItemsCount write SetItemsCount;
6229 {* |<#listview>
6230 Returns item count for ListView control. It is possible to use Count
6231 property instead when obtaining of item count is needed only. But this this
6232 property allows also to set actual count of list view items when a list
6233 view is virtual. }
6235 property LVCurItem: Integer read GetLVCurItem write SetLVCurItem;
6236 {* |<#listview>
6237 Returns first selected item index in a list view. See also LVNextSelected
6238 and LVNextItem functions. }
6240 function LVNextItem( IdxPrev: Integer; Attrs: DWORD ): Integer;
6241 {* |<#listview>
6242 Returns an index of the next after IdxPrev item with given attributes in
6243 the list view. }
6244 function LVNextSelected( IdxPrev: Integer ): Integer;
6245 {* |<#listview>
6246 Returns an index of next (after IdxPrev) selected item in a list view. }
6248 function LVAdd( const aText: String; ImgIdx: Integer; State: TListViewItemState;
6249 StateImgIdx, OverlayImgIdx: Integer; Data: DWORD ): Integer;
6250 {* |<#listview>
6251 Adds new line to the end of ListView control. Only content of item itself
6252 is set (aText, ImgIdx). To change other column text and attributes of
6253 item added, use appropriate properties / methods ().
6254 |<br>
6255 Returns an index of added item.
6256 |<br>
6257 There is no Unicode version defined, use LVItemAddW instead. }
6258 function LVItemAdd( const aText: String ): Integer;
6259 {* |<#listview>
6260 Adds an item to the end of list view. Returns an index of the item added. }
6261 {$IFNDEF _FPC}
6262 {$IFNDEF _D2}
6263 function LVItemAddW( const aText: WideString ): Integer;
6264 {* |<#listview>
6265 Adds an item to the end of list view. Returns an index of the item added. }
6266 {$ENDIF _D2}
6267 {$ENDIF _FPC}
6268 function LVInsert( Idx: Integer; const aText: String; ImgIdx: Integer;
6269 State: TListViewItemState; StateImgIdx, OverlayImgIdx: Integer; Data: DWORD ): Integer;
6270 {* |<#listview>
6271 Inserts new line before line with index Idx in ListView control. Only
6272 content of item itself is set (aText, ImgIdx). To change other column
6273 text and attributes of item added, use appropriate properties / methods ().
6274 if ImgIdx = I_IMAGECALLBACK, event handler OnGetLVItemImgIdx is responsible
6275 for returning image index for an item ( /// not implemented yet /// )
6276 Pass StateImgIdx and OverlayImgIdx = 0 (ignored in that case) or 1..15 to
6277 use correspondent icon from ImageListState image list.
6278 |<br> Returns an index of item inserted.
6279 |<br> There is no unicode version of this method, use LVItemInsertW. }
6280 function LVItemInsert( Idx: Integer; const aText: String ): Integer;
6281 {* |<#listview>
6282 Inserts an item to Idx position. }
6283 {$IFNDEF _FPC}
6284 {$IFNDEF _D2}
6285 function LVItemInsertW( Idx: Integer; const aText: WideString ): Integer;
6286 {* |<#listview>
6287 Inserts an item to Idx position. }
6288 {$ENDIF _D2}
6289 {$ENDIF _FPC}
6291 procedure LVDelete( Idx: Integer );
6292 {* |<#listview>
6293 Deletes item of ListView with subitems (full row - in lvsDetail view style. }
6294 procedure LVSetItem( Idx, Col: Integer; const aText: String; ImgIdx: Integer;
6295 State: TListViewItemState; StateImgIdx, OverlayImgIdx: Integer; Data: DWORD );
6296 {* |<#listview>
6297 Use this method to set item data and item columns data for ListView control.
6298 It is possible to pass I_SKIP as ImgIdx, StateImgIdx, OverlayImgIdx values to
6299 skip setting this fields. But all other are set always. Like in LVInsert /
6300 LVAdd, ImgIdx can be I_IMAGECALLBACK to determine that image will be
6301 retrieved in OnGetItemImgIdx event handler when needed.
6302 |<br>
6303 If this method is called to set data for column > 0, parameters ImgIdx and
6304 Data are ignored anyway.
6305 |<br> There is no unicode version of this method, use other methods
6306 to set up listed properties separately using correspondent W-functions. }
6308 property LVItemState[ Idx: Integer ]: TListViewItemState read LVGetItemState write LVSetItemState;
6309 {* |<#listview>
6310 Access to list view item states set [lvisBlend, lvisHighlight, lvisFocus,
6311 lvisSelect]. When assign new value to the property, it is possible to use
6312 special index value -1 to change state for all items for a list view
6313 (but only when lvoMultiselect style is applied to the list view, otherwise
6314 index -1 is referring to the last item of the list view). }
6316 property LVItemIndent[ Idx: Integer ]: Integer read LVGetItemIndent write LVSetItemIndent;
6317 {* Item indentation. Indentation is calculated as this value multiplied to
6318 image list ImgWidth value (Image list must be applied to list view).
6319 Note: indentation supported only if IE3.0 or higher installed. }
6320 property LVItemStateImgIdx[ Idx: Integer ]: Integer read LVGetSttImgIdx write LVSetSttImgIdx;
6321 {* |<#listview>
6322 Access to state image of the item. Use index -1 to assign the same state
6323 image index to all items of the list view at once (fast).
6324 Option lvoCheckBoxes just means, that control itself creates special inner
6325 image list for two state images. Later it is possible to examine checked
6326 state for items or set checked state programmatically by changing
6327 LVItemStateImgIdx[ ] property. Value 1 corresponds to unchecked state,
6328 2 to checked. Value 0 allows to remove checkbox at all. So, to check all
6329 added items by default (e.g.), do following:
6330 ! ListView1.LVItemStateImgIdx[ -1 ] := 2;
6331 |<br>Use 1-based index of the image
6332 in image list ImageListState. Value 0 reserved to use as "no state image".
6333 Values 1..15 can be used only - this is the Windows restriction on
6334 state images. }
6335 property LVItemOverlayImgIdx[ Idx: Integer ]: Integer read LVGetOvlImgIdx write LVSetOvlImgIdx;
6336 {* |<#listview>
6337 Access to overlay image of the item. Use index -1 to assign the same
6338 overlay image to all items of the list view at once (fast). }
6339 property LVItemData[ Idx: Integer ]: DWORD read LVGetItemData write LVSetItemData;
6340 {* |<#listview>
6341 Access to user defined data, assiciated with the item of the list view. }
6342 procedure LVSelectAll;
6343 {* |<#listview>
6344 Call this method to select all the items of the list view control. }
6345 property LVSelCount: Integer read GetSelLength write SetSelLength;
6346 {* |<#listview>
6347 Returns number of items selected in listview. }
6348 property LVItemImageIndex[ Idx: Integer ]: Integer read LVGetItemImgIdx write LVSetItemImgIdx;
6349 {* |<#listview>
6350 Image index of items in listview. When an item is created (using LVItemAdd
6351 or LVItemInsert), image index 0 is set by default (not -1 like in VCL!). }
6352 property LVItems[ Idx, Col: Integer ]: String read LVGetItemText write LVSetItemText;
6353 {* |<#listview>
6354 Access to List View item text. }
6355 {$IFNDEF _FPC}
6356 {$IFNDEF _D2}
6357 property LVItemsW[ Idx, Col: Integer ]: WideString read LVGetItemTextW write LVSetItemTextW;
6358 {* |<#listview>
6359 Access to List View item text. }
6360 {$ENDIF _D2}
6361 {$ENDIF _FPC}
6362 function LVItemRect( Idx: Integer; Part: TGetLVItemPart ): TRect;
6363 {* |<#listview>
6364 Returns rectangle occupied by given item part(s) in ListView window.
6365 Empty rectangle is returned, if the item is not viewing currently. }
6366 function LVSubItemRect( Idx, ColIdx: Integer ): TRect;
6367 {* |<#listview>
6368 Returns rectangle occupied by given item's subitem in ListView window,
6369 in lvsDetail or lvsDetailNoHeader style. Empty rectangle (0,0,0,0) is
6370 returned if the item is not viewing currently. Left or/and right bounds
6371 of the rectangle returned can be outbound item rectangle if only a part
6372 of the subitem is visible or the subitem is not visible in the item,
6373 which is visible itself. }
6374 property LVItemPos[ Idx: Integer ]: TPoint read LVGetItemPos write LVSetItemPos;
6375 {* |<#listview>
6376 Position of List View item (can be changed in icon or small icon view). }
6377 function LVItemAtPos( X, Y: Integer ): Integer;
6378 {* |<#listview>
6379 Return index of item at the given position. }
6380 function LVItemAtPosEx( X, Y: Integer; var Where: TWherePosLVItem ): Integer;
6381 {* |<#listview>
6382 Retrieves index of item and sets in Where, what part of item is under
6383 given coordinates. If there are no items at the specified position,
6384 -1 is returned. }
6385 procedure LVMakeVisible( Item: Integer; PartiallyOK: Boolean );
6386 {* |<#listview>
6387 Makes listview item visible. Ignred when Item passed < 0. }
6388 procedure LVEditItemLabel( Idx: Integer );
6389 {* |<#listview>
6390 Begins in-place editing of item label (first column text). }
6391 procedure LVSort;
6392 {* |<#listview>
6393 Initiates sorting of list view items. This sorting procedure is available only
6394 for Win2K, WinNT4 with IE5, Win98 or Win95 with IE5. See also LVSortData. }
6395 procedure LVSortData;
6396 {* |<#listview>
6397 Initiates sorting of list view items. This sorting procedure is always available
6398 in Windows95/98, NT/2000. But OnCompareLVItems procedure receives not indexes of
6399 items compared but its Data field associated instead. }
6400 procedure LVSortColumn( Idx: Integer );
6401 {* |<#listview>
6402 This is a method to simplify sort by column. Just call it in your OnColumnClick
6403 event passing column index and enjoy with your list view sorted automatically
6404 when column header is clicked. Requieres Windows2000 or Winows98, not supported
6405 under WinNT 4.0 and below and under Windows95.
6406 |<br>
6407 Either lvoSortAscending or lvoSortDescending option must be set in
6408 LVOptions, otherwise no sorting is performed. }
6409 function LVIndexOf( const S: String ): Integer;
6410 {* Returns first list view item index with caption matching S.
6411 The same as LVSearchFor( S, -1, FALSE ). }
6412 {$IFNDEF _FPC}
6413 {$IFNDEF _D2}
6414 function LVIndexOfW( const S: WideString ): Integer;
6415 {* Returns first list view item index with caption matching S.
6416 The same as LVSearchForW( S, -1, FALSE ). }
6417 {$ENDIF _D2}
6418 {$ENDIF _FPC}
6419 function LVSearchFor( const S: String; StartAfter: Integer; Partial: Boolean ): Integer;
6420 {* Searches an item with Caption equal to S (or starting from S, if Partial = TRUE).
6421 Searching is started after an item specified by StartAfter parameter. }
6422 {$IFNDEF _FPC}
6423 {$IFNDEF _D2}
6424 function LVSearchForW( const S: WideString; StartAfter: Integer; Partial: Boolean ): Integer;
6425 {* Searches an item with Caption equal to S (or starting from S, if Partial = TRUE).
6426 Searching is started after an item specified by StartAfter parameter. }
6427 {$ENDIF _D2}
6428 {$ENDIF _FPC}
6430 //======== List view page:
6431 property LVTopItem: Integer index LVM_GETTOPINDEX read GetIntVal; //LVGetTopItem;
6432 {* |<#listview>
6433 Returns index of topmost visible item of ListView in lvsList view style. }
6434 property LVPerPage: Integer index LVM_GETCOUNTPERPAGE read GetIntVal; //LVGetPerPage;
6435 {* |<#listview>
6436 Returns the number of fully-visible items if successful. If the current
6437 view is icon or small icon view, the return value is the total number
6438 of items in the list view control. }
6440 //======== List View specific events:
6441 property OnEndEditLVItem: TOnEditLVItem read fOnEditLVITem write SetOnEditLVItem;
6442 {* |<#listview>
6443 Called when edit of an item label in ListView control finished. Return
6444 True to accept new label text, or false - to not accept it (item label
6445 will not be changed). If handler not set to an event, all changes are
6446 accepted. }
6448 property OnDeleteLVItem: TOnDeleteLVItem read fOnDeleteLVItem write SetOnDeleteLVItem;
6449 {* |<#listview>
6450 Called for every deleted list view item. }
6451 property OnDeleteAllLVItems: TOnEvent read fOnDeleteAllLVItems write SetOnDeleteAllLVItems;
6452 {* |<#listview>
6453 Called when all the items of the list view control are to be deleted. If after
6454 returning from this event handler event OnDeleteLVItem is yet assigned,
6455 an event OnDeleteLVItem will be called for every deleted item. }
6456 property OnLVData: TOnLVData read fOnLVData write SetOnLVData;
6457 {* |<#listview>
6458 Called to provide virtual list view with actual data. To use list view as
6459 virtaul list view, define also lvsOwnerData style and set Count property
6460 to actual row count of the list view. This manner of working with list view
6461 control can greatly improve performance of an application when working with
6462 huge data sets represented in listview control. }
6463 {$IFNDEF _FPC}
6464 {$IFNDEF _D2}
6465 property OnLVDataW: TOnLVDataW read fOnLVDataW write SetOnLVDataW;
6466 {* |<#listview>
6467 The same as OnLVData, but for unicode version of the list view allows
6468 to return WideString text in the event handler. Though for unicode list
6469 view it is still possible to use ordinary event OnLVData, it is
6470 very recommended to use this event istead. }
6471 {$ENDIF _D2}
6472 {$ENDIF _FPC}
6474 property OnCompareLVItems: TOnCompareLVItems read fOnCompareLVItems write fOnCompareLVItems;
6475 {* |<#listview>
6476 Event to compare two list view items during sort operation (initiated by
6477 LVSort method call). Do not send any messages to the list view control
6478 while it is sorting - results can be unpredictable! }
6479 property OnColumnClick: TOnLVColumnClick read fOnColumnClick write SetOnColumnClick;
6480 {* |<#listview>
6481 This event handler is called when column of the list view control is clicked.
6482 You can use this event to initiate sorting of list view items by this column. }
6483 property OnLVStateChange: TOnLVStateChange read FOnLVStateChange write SetOnLVStateChange;
6484 {* |<#listview>
6485 This event occure when an item or items range in list view control are
6486 changing its state (e.g. selected or unselected). }
6487 property OnLVDelete: TOnLVDelete read FOnLVDelete write SetOnLVDelete;
6488 {* |<#listview>
6489 This event is called when an item is deleted in the listview.
6490 Do not add, delete, or rearrange items in the list view while processing
6491 this notification. }
6492 property OnDrawItem: TOnDrawItem read fOnDrawItem write SetOnDrawItem;
6493 {* |<#listview>
6494 |<#listbox>
6495 |<#combo>
6496 This event can be used to implemet custom drawing for list view, list box, dropped
6497 list of a combobox. For a list view, custom drawing using this event is possible
6498 only in lvsDetail and lvsDetailNoHeader styles, and OnDrawItem is called to draw
6499 entire row at once only. See also OnLVCustomDraw event. }
6501 property OnLVCustomDraw: TOnLVCustomDraw read FOnLVCustomDraw write SetOnLVCustomDraw;
6502 {* |<#listview>
6503 Custom draw event for listview. For every item to be drawn, this event
6504 can be called several times during a single drawing cycle - depending on
6505 a result, returned by an event handler. Stage can have one of following
6506 values:
6507 |<pre>
6508 CDDS_PREERASE
6509 CDDS_POSTERASE
6510 CDDS_ITEMPREERASE
6511 CDDS_PREPAINT
6512 CDDS_ITEMPREPAINT
6513 CDDS_ITEM
6514 CDDS_SUBITEM + CDDS_ITEMPREPAINT
6515 CDDS_SUBITEM + CDDS_ITEMPOSTPAINT
6516 CDDS_ITEMPOSTPAINT
6517 CDDS_POSTPAINT
6518 </pre>
6519 When called, see on Stage to get know, on what stage the event is
6520 activated. And depend on the stage and on what you want to paint,
6521 return a value as a result, which instructs the system, if to use
6522 default drawing on this (and follows) stage(s) for the item, and if
6523 to notify further about different stages of drawing the item during
6524 this drawing cycle. Possible values to return are:
6525 |<pre>
6526 CDRF_DODEFAULT - perform default drawing. Do not notify further for this
6527 item (subitem) (or for entire listview, if called with
6528 flag CDDS_ITEM reset - ?);
6529 CDRF_NOTIFYITEMDRAW - return this value, when the event is called the
6530 first time in a cycle of drawing, with ItemIdx = -1 and
6531 flag CDDS_ITEM reset in Stage parameter;
6532 CDRF_NOTIFYPOSTERASE - usually can be used to provide default erasing,
6533 if you want to perform drawing immediately after that;
6534 CDRF_NOTIFYPOSTPAINT - return this value to provide calling the event
6535 after performing default drawing. Useful when you wish
6536 redraw only a part of the (sub)item;
6537 CDRF_SKIPDEFAULT - return this value to inform the system that all
6538 drawing is done and system should not peform any more
6539 drawing for the (sub)item during this drawing cycle.
6540 CDRF_NEWFONT - informs the system, that font is changed and default
6541 drawing should be performed with changed font;
6542 |</pre>
6543 If you want to get notifications for each subitem, do not use option
6544 lvoOwnerDrawFixed, because such style prevents system from notifying
6545 the application for each subitem to be drawn in the listview and only
6546 notifications will be sent about entire items.
6547 |<br>
6548 See also NM_CUSTOMDRAW in API Help.
6551 procedure Set_LVItemHeight(Value: Integer);
6552 function SetLVItemHeight(Value: Integer): PControl;
6553 property LVItemHeight: Integer read fLVItemHeight write Set_LVItemHeight;
6556 //======== TreeView specific properties and methods:
6557 function TVInsert( nParent, nAfter: THandle; const Txt: String ): THandle;
6558 {* |<#treeview>
6559 Inserts item to a tree view. If nParent is 0 or TVI_ROOT, the item is
6560 inserted at the root of tree view. It is possible to pass following special
6561 values as nAfter parameter:
6562 |<pre>
6563 TVI_FIRST Inserts the item at the beginning of the list.
6564 TVI_LAST Inserts the item at the end of the list.
6565 TVI_SORT Inserts the item into the list in alphabetical order.
6566 |</pre> }
6567 {$IFNDEF _FPC}
6568 {$IFNDEF _D2}
6569 function TVInsertW( nParent, nAfter: THandle; const Txt: WideString ): THandle;
6570 {* |<#treeview>
6571 Inserts item to a tree view. If nParent is 0 or TVI_ROOT, the item is
6572 inserted at the root of tree view. It is possible to pass following special
6573 values as nAfter parameter:
6574 |<pre>
6575 TVI_FIRST Inserts the item at the beginning of the list.
6576 TVI_LAST Inserts the item at the end of the list.
6577 TVI_SORT Inserts the item into the list in alphabetical order.
6578 |</pre><br>
6579 This version of the method is Unicode. The tree view control should be
6580 set up as unicode control calling Perform( TVM_SETUNICODEFORMAT, 1, 0 ),
6581 and conditional symbol UNICODE_CTRLS must be defined to provide event
6582 handling for such kind of tree view (and other Unicode) controls. }
6583 {$ENDIF _D2}
6584 {$ENDIF _FPC}
6585 procedure TVDelete( Item: THandle );
6586 {* |<#treeview>
6587 Removes an item from the tree view. If value TVI_ROOT is passed, all items
6588 are removed. }
6590 property TVSelected: THandle index TVGN_CARET read TVGetItemIdx write TVSetItemIdx;
6591 {* |<#treeview>
6592 Returns or sets currently selected item handle in tree view. }
6594 property TVDropHilighted: THandle index TVGN_DROPHILITE read TVGetItemIdx write TVSetItemIdx;
6595 {* |<#treeview>
6596 Returns or sets item, which is currently highlighted as a drop target. }
6597 property TVDropHilited: THandle index TVGN_DROPHILITE read TVGetItemIdx write TVSetItemIdx;
6598 {* The same as TVDropHilighted. }
6599 property TVFirstVisible: THandle index TVGN_FIRSTVISIBLE read TVGetItemIdx write TVSetItemIdx;
6600 {* |<#treeview>
6601 Returns or sets given item to top of tree view. }
6603 property TVIndent: Integer index TVM_GETINDENT read GetIntVal write SetIntVal;
6604 {* |<#treeview>
6605 The amount, in pixels, that child items are indented relative to their
6606 parent items. }
6607 property TVVisibleCount: Integer index TVM_GETVISIBLECOUNT read GetIntVal;
6608 {* |<#treeview>
6609 Returns number of fully (not partially) visible items in tree view. }
6611 property TVRoot: THandle index TVGN_ROOT read TVGetItemIdx;
6612 {* |<#treeview>
6613 Returns handle of root item in tree view (or 0, if tree is empty). }
6614 property TVItemChild[ Item: THandle ]: THandle index TVGN_CHILD read TVGetItemNext;
6615 {* |<#treeview>
6616 Returns first child item for given one. }
6617 property TVItemHasChildren[ Item: THandle ]: Boolean read TV_GetItemHasChildren write TV_SetItemHasChildren;
6618 {* |<#treeview>
6619 TRUE, if an Item has children. Set this value to true if you want to
6620 force [+] sign appearing left from the node, even if there are no
6621 subnodes added to the node yet. }
6622 property TVItemChildCount[ Item: THandle ]: Integer read TV_GetItemChildCount;
6623 {* |<#treeview>
6624 Returns number of node child items in tree view.
6626 property TVItemNext[ Item: THandle ]: THandle index TVGN_NEXT read TVGetItemNext;
6627 {* |<#treeview>
6628 Returns next sibling item handle for given one (or 0, if passed item is
6629 the last child for its parent node). }
6630 property TVItemPrevious[ Item: THandle ]: THandle index TVGN_PREVIOUS read TVGetItemNext;
6631 {* |<#treeview>
6632 Returns previous sibling item (or 0, if the is no such item). }
6633 property TVItemNextVisible[ Item: THandle ]: THandle index TVGN_NEXTVISIBLE read TVGetItemNext;
6634 {* |<#treeview>
6635 Returns next visible item (passed item must be visible too, to determine,
6636 if it is really visible, use property TVItemRect or TVItemVisible. }
6637 property TVItemPreviousVisible[ Item: THandle ]: THandle index TVGN_PREVIOUSVISIBLE read TVGetItemNext;
6638 {* |<#treeview>
6639 Returns previous visible item. }
6640 property TVItemParent[ Item: THandle ]: THandle index TVGN_PARENT read TVGetItemNext;
6641 {* |<#treeview>
6642 Returns parent item for given one (or 0 for root item). }
6644 property TVItemText[ Item: THandle ]: String read TVGetItemText write TVSetItemText;
6645 {* |<#treeview>
6646 Text of tree view item. }
6647 {$IFNDEF _FPC}
6648 {$IFNDEF _D2}
6649 property TVItemTextW[ Item: THandle ]: WideString read TVGetItemTextW write TVSetItemTextW;
6650 {* |<#treeview>
6651 Text of tree view item. }
6652 {$ENDIF _D2}
6653 {$ENDIF _FPC}
6654 function TVItemPath( Item: THandle; Delimiter: Char ): String;
6655 {* |<#treeview>
6656 Returns full path from the root item to given item. Path is calculated
6657 as a concatenation of all parent nodes text strings, separated by
6658 given delimiter character.
6659 |<br>Please note, that returned path has no trailing delimiter, this
6660 character is only separating different parts of the path.
6661 |<br>If Item is not specified ( =0 ), path is returned
6662 for Selected item. }
6663 {$IFNDEF _FPC}
6664 {$IFNDEF _D2}
6665 function TVItemPathW( Item: THandle; Delimiter: WideChar ): WideString;
6666 {* |<#treeview>
6667 Returns full path from the root item to given item. Path is calculated
6668 as a concatenation of all parent nodes text strings, separated by
6669 given delimiter character. If Item is not specified ( =0 ), path is returned
6670 for Selected item. }
6671 {$ENDIF _D2}
6672 {$ENDIF _FPC}
6674 property TVItemRect[ Item: THandle; TextOnly: Boolean ]: TRect read TVGetItemRect;
6675 {* |<#treeview>
6676 Returns rectangle, occupied by an item in tree view. }
6678 property TVItemVisible[ Item: THandle ]: Boolean read TVGetItemVisible write TVSetITemVisible;
6679 {* |<#treeview>
6680 Returs True, if item is visible in tree view. It is also possible to
6681 assign True to this property to ensure that a tree view item is visible
6682 (if False is assigned, this does nothing). }
6683 function TVItemAtPos( x, y: Integer; var Where: DWORD ): THandle;
6684 {* |<#treeview>
6685 Returns handle of item found at specified position (relative to upper left
6686 corener of client area of the tree view). If no item found, 0 is returned.
6687 Variable Where receives additional flags combination, describing more
6688 detailed, on which part of item or tree view given point is located,
6689 such as:
6690 |<pre>
6691 TVHT_ABOVE Above the client area
6692 TVHT_BELOW Below the client area
6693 TVHT_NOWHERE In the client area, but below the last item
6694 TVHT_ONITEM On the bitmap or label associated with an item
6695 TVHT_ONITEMBUTTON On the button associated with an item
6696 TVHT_ONITEMICON On the bitmap associated with an item
6697 TVHT_ONITEMINDENT In the indentation associated with an item
6698 TVHT_ONITEMLABEL On the label (string) associated with an item
6699 TVHT_ONITEMRIGHT In the area to the right of an item
6700 TVHT_ONITEMSTATEICON On the state icon for a tree-view item that is in a user-defined state
6701 TVHT_TOLEFT To the right of the client area
6702 TVHT_TORIGHT To the left of the client area
6703 |</pre> }
6705 property TVRightClickSelect: Boolean read fTVRightClickSelect write SetTVRightClickSelect;
6706 {* |<#treeview>
6707 Set this property to True to allow change selection to an item, clicked with right mouse button. }
6708 property TVEditing: Boolean read fEditing;
6709 {* |<#treeview>
6710 Returns True, if tree view control is editing its item label. }
6712 property TVItemBold[ Item: THandle ]: Boolean index TVIS_BOLD read TVGetItemStateFlg write TVSetItemStateFlg;
6713 {* |<#treeview>
6714 True, if item is bold. }
6715 property TVItemCut[ Item: THandle ]: Boolean index TVIS_CUT read TVGetITemStateFlg write TVSetItemStateFlg;
6716 {* |<#treeview>
6717 True, if item is selected as part of "cut and paste" operation. }
6718 property TVItemDropHighlighted[ Item: THandle ]: Boolean index TVIS_DROPHILITED read TVGetITemStateFlg write TVSetItemStateFlg;
6719 {* |<#treeview>
6720 True, if item is selected as drop target. }
6721 property TVItemDropHilited[ Item: THandle ]: Boolean index TVIS_DROPHILITED read TVGetITemStateFlg write TVSetItemStateFlg;
6722 {* The same as TVItemDropHighlighted. }
6723 property TVItemExpanded[ Item: THandle ]: Boolean index TVIS_EXPANDED read TVGetITemStateFlg; // write TVSetItemStateFlg;
6724 {* |<#treeview>
6725 True, if item's list of child items is currently expanded. To change
6726 expanded state, use method TVExpand. }
6727 property TVItemExpandedOnce[ Item: THandle ]: Boolean index TVIS_EXPANDEDONCE read TVGetITemStateFlg; // write TVSetItemStateFlg;
6728 {* |<#treeview>
6729 True, if item's list of child items has been expanded at least once. }
6730 property TVItemSelected[ Item: THandle ]: Boolean index TVIS_SELECTED read TVGetITemStateFlg write TVSetItemStateFlg;
6731 {* |<#treeview>
6732 True, if item is selected. }
6734 procedure TVExpand( Item: THandle; Flags: DWORD );
6735 {* |<#treeview>
6736 Call it to expand/collapse item's child nodes. Possible values for Flags
6737 parameter are:
6738 <pre>
6739 TVE_COLLAPSE Collapses the list.
6740 TVE_COLLAPSERESET Collapses the list and removes the child items. Note
6741 that TVE_COLLAPSE must also be specified.
6742 TVE_EXPAND Expands the list.
6743 TVE_TOGGLE Collapses the list if it is currently expanded or
6744 expands it if it is currently collapsed.
6745 </pre>
6747 procedure TVSort( N: THandle );
6748 {* |<#treeview>
6749 By Alex Mokrov. Sorts treeview. If N = 0, entire treeview is sorted.
6750 Otherwise, children of the given node only.
6753 property TVItemImage[ Item: THandle ]: Integer index TVIF_IMAGE read TVGetItemImage write TVSetItemImage;
6754 {* |<#treeview>
6755 Image index for an item of tree view. To tell that there are no image
6756 set, use index -2 (value -1 is reserved for callback image). }
6757 property TVItemSelImg[ Item: THandle ]: Integer index TVIF_SELECTEDIMAGE read TVGetItemImage write TVSetItemImage;
6758 {* |<#treeview>
6759 Image index for an item of tree view in selected state. Use value -2 to
6760 provide no image, -1 used for callback image. }
6761 property TVItemOverlay[ Item: THandle ]: Integer index TVIS_OVERLAYMASK or $80000
6762 read TVGetItemImage write TVSetItemImage;
6763 {* |<#treeview>
6764 Overlay image index for an item in tree view. }
6765 property TVItemStateImg[ Item: THandle ]: Integer index TVIS_STATEIMAGEMASK or $C0000
6766 read TVGetItemImage write TVSetItemImage;
6767 {* |<#treeview>
6768 State image index for an item in tree view. Use 1-based index of the image
6769 in image list ImageListState. Value 0 reserved to use as "no state image".
6770 Values 1..15 can be used only - this is the Windows restriction on
6771 state images. }
6773 property TVItemData[ Item: THandle ]: Pointer read TVGetItemData write TVSetItemData;
6774 {* |<#treeview>
6775 Stores any program-defined pointer with the item. }
6776 procedure TVEditItem( Item: THandle );
6777 {* |<#treeview>
6778 Begins editing given item label in tree view. }
6779 procedure TVStopEdit( Cancel: Boolean );
6780 {* |<#treeview>
6781 Ends editing item label, started by user or explicitly by TVEditItem method. }
6783 property OnTVBeginDrag: TOnTVBeginDrag read fOnTVBeginDrag write fOnTVBeginDrag;
6784 {* |<#treeview>
6785 Is called for tree view, when its item is to be dragging. }
6786 property OnTVBeginEdit: TOnTVBeginEdit read fOnTVBeginEdit write fOnTVBeginEdit;
6787 {* |<#treeview>
6788 Is called for tree view, when its item label is to be editing. }
6789 property OnTVEndEdit: TOnTVEndEdit read fOnTVEndEdit write fOnTVEndEdit;
6790 {* |<#treeview>
6791 Is called when item label is edited. It is possible to cancel
6792 edit, returning False as a result. }
6793 property OnTVExpanding: TOnTVExpanding read fOnTVExpanding write fOnTVExpanding;
6794 {* |<#treeview>
6795 Is called just before expanding/collapsing item. It is possible to
6796 return False to prevent expanding item. }
6797 property OnTVExpanded: TOnTVExpanded read fOnTVExpanded write fOnTVExpanded;
6798 {* |<#treeview>
6799 Is called after expanding/collapsing item children. }
6800 property OnTVDelete: TOnTVDelete read fOnTVDelete write SetOnTVDelete;
6801 {* |<#treeview>
6802 Is called just before deleting item. You may use this event to free
6803 resources, associated with an item (see TVItemData property). }
6804 //----------------- by Sergey Shisminzev:
6805 property OnTVSelChanging: TOnTVSelChanging read fOnTVSelChanging write fOnTVSelChanging;
6806 {* |<#treeview>
6807 Is called before changing the selection. The handler can return FALSE
6808 to prevent changing the selection. }
6809 //--------------------------------------
6811 //======== Toolbar specific methods:
6812 procedure TBAddBitmap( Bitmap: HBitmap );
6813 {* |<#toolbar>
6814 Adds bitmaps to a toolbar. You can pass special values as Bitmap to
6815 add one of predefined system button images bitmaps:
6816 |<br> THandle(-1) to add standard small icons,
6817 |<br> THandle(-2) to add standard large icons,
6818 |<br> THandle(-5) to add standard small view icons,
6819 |<br> THandle(-6) to add standard large view icons,
6820 |<br> THandle(-9) to add standard small view icons,
6821 |<br> THandle(-10) to add standard large view icons,
6822 (in that case use following values as indexes to the standard and view
6823 bitmaps:
6824 |<br>
6825 STD_COPY, STD_CUT, STD_DELETE, STD_FILENEW, STD_FILEOPEN, STD_FILESAVE,
6826 STD_FIND, STD_HELP, STD_PASTE, STD_PRINT, STD_PRINTPRE, STD_PROPERTIES,
6827 STD_REDO, STD_REPLACE, STD_UNDO,
6828 |<br>
6829 VIEW_LARGEICONS, VIEW_SMALLICONS,
6830 VIEW_LIST, VIEW_DETAILS, VIEW_SORTNAME, VIEW_SORTSIZE, VIEW_SORTDATE,
6831 VIEW_SORTTYPE (use it as parameters BtnImgIdxArray in TBAddButtons or
6832 TBInsertButtons methods, and in assigning value to TBButtonImage[ ]
6833 property).
6834 Added bitmaps have indeces starting from previous count of images
6835 (as these are appended to existing - if any).
6836 |<br>
6837 Note, that if You add your own (custom) bitmap, it is not transparent.
6838 Do not assume that clSilver is always equal to clBtnFace. Use API
6839 function CreateMappedBitmap to load bitmap from resource and map
6840 desired colors as you wish (e.g., convert clTeal to clBtnFace). Or,
6841 call defined in KOL function LoadMappedBitmap to do the same more easy.
6842 Unfortunately, resource identifier for bitmap to pass it to LoadMappedBitmap
6843 or to CreateMappedBitmap seems must be integer, so it is necessary to
6844 create rc-file manually and compile using Borland Resource Compiler to
6845 figure it out. }
6848 function TBAddButtons( const Buttons: array of PChar; const BtnImgIdxArray: array
6849 of Integer ): Integer;
6850 {* |<#toolbar>
6851 Adds buttons to toolbar. Last string in Buttons array *must* be empty
6852 ('' or nil), so to add buttons without text, pass ' ' string (one space
6853 char). It is not necessary to provide image indexes for all
6854 buttons (it is sufficient to assign index for first button only).
6855 But in place, correspondent to separator button (defined by string '-'),
6856 any integer must be passed to assign follow image indexes correctly.
6857 See example.
6858 |*Toolbar adding buttons sample.
6859 Code below shows how to call TBAddButtons method to add two buttons with
6860 a separator between these buttons. idxNew and idxOld are integer
6861 expressions assigning image indexes to buttons 'New' and 'Old'. This
6862 indexes are zero-based and refer to bitmap images, added earlier (either
6863 in creating toolbar by call of NewToolbar or later in call of TBAddBitmap).
6865 ! TBAddButtons( [ '&New', '-', '&Old', '' ], [ idxNew, 0, idxOld ] );
6868 To add check buttons, use prefix '+' or '-' in button definition
6869 string. If next character is '!', such buttons are grouped to a
6870 radio-group. Also, it is possible to use '^' prefix (must be first) to
6871 define button with small drop-down section (use also OnTBDropDown event
6872 to respond to clicking drop down section of such buttons).
6873 |<br>
6874 This function returns command id for first added button (other
6875 id's can be calculated incrementing the result by one for each
6876 button, except separators, which have no command id).
6877 |<br>
6878 Note: for static toolbar (single in application and created
6879 once) ids are started from value 100. }
6881 function TBInsertButtons( BeforeIdx: Integer; Buttons: array of PChar;
6882 BtnImgIdxArray: array of Integer ): Integer;
6883 {* |<#toolbar>
6884 Inserts buttons before button with given index on toolbar. Returns
6885 command identifier for first button inserted (other can be calculated
6886 incrementing returned value needed times. See also TBAddButtons. }
6888 procedure TBDeleteButton( BtnID: Integer );
6889 {* |<#toolbar>
6890 Deletes single button given by its command id. To delete separator,
6891 use TBDeleteBtnByIdx instead. }
6893 procedure TBDeleteBtnByIdx( Idx: Integer );
6894 {* |<#toolbar>
6895 Deletes single button given by its index in toolbar (not by command ID). }
6897 procedure TBAssignEvents( BtnID: Integer; Events: array of TOnToolbarButtonClick );
6898 {* |<#toolbar>
6899 Allows to assign separate OnClick events for every toolbar button.
6900 BtnID should be toolbar button ID or index of the first button to
6901 assign event. If it is an ID, events are assigned to buttons in
6902 creation order. Otherwise, events are assigned in placement order.
6903 Anyway, separator buttons are not skipped, so pass at least nil for such
6904 button as an event.
6905 |<br>
6906 Please note, that though not all buttons should exist before
6907 assigning events to it, therefore at least the first button
6908 (specified by BtnID) must be already added before calling TBAssignEvents. }
6910 procedure TBResetImgIdx( BtnID, BtnCount: Integer );
6911 {* |<#toolbar>
6912 Resets image index for BtnCount buttons starting from BtnID. }
6914 property CurItem: Integer read fCurItem;
6915 {* |<#toolbar>
6916 For toolbar, in OnClick event this property can be used to determine
6917 which button was clicked (100-based button id in toolbar). It is also
6918 possible to use CurIndex property (zero-based) for this purpose as
6919 well, but do not assume, that CurItem always equal to CurIndex+100.
6920 At least, it is possible to call TBItem2Index function to convert
6921 button ID to its index in toolbar.
6922 |<br>
6923 In case, when button (or toolbar itself) is clicked using right
6924 mouse button, CurItem and CurIndex are always set to -1. To further
6925 determine which button was clicked, get mouse coordinates on screen,
6926 apply Screen2Client method of toolbar control to it and then use
6927 TBButtonAtPos function to determine which button was under cursor.
6930 property TBButtonCount: Integer read GetItemsCount; //TBGetButtonCount;
6931 {* |<#toolbar>
6932 Returns count of buttons on toolbar. The same as Count. }
6934 property TBBtnImgWidth: Integer read fTBBtnImgWidth write fTBBtnImgWidth;
6935 {* |<#toolbar>
6936 Custom toolbar buttons width. Set it before assigning buttons bitmap.
6937 Changing this property after assigning the bitmap has no effect. }
6939 function TBItem2Index( BtnID: Integer ): Integer;
6940 {* |<#toolbar>
6941 Converts button command id to button index for tool bar. }
6943 function TBIndex2Item( Idx: Integer ): Integer;
6944 {* |<#toolbar>
6945 Converts toolbar button index to its command ID. }
6947 property TBButtonEnabled[ BtnID: Integer ]: Boolean index TB_ENABLEBUTTON
6948 read TBGetBtnStt write TBSetBtnStt;
6949 {* |<#toolbar>
6950 Obvious. }
6952 property TBButtonVisible[ BtnID: Integer ]: Boolean read TBGetButtonVisible
6953 write TBSetButtonVisible;
6954 {* |<#toolbar>
6955 Allows to hide/show some of toolbar buttons. }
6957 property TBButtonChecked[ BtnID: Integer ]: Boolean index TB_CHECKBUTTON
6958 read TBGetBtnStt write TBSetBtnStt;
6959 {* |<#toolbar>
6960 Allows to determine 'checked' state of a button (e.g., radio-button),
6961 and to check it programmatically. }
6963 property TBButtonMarked[ BtnID: Integer ]: Boolean index TB_MARKBUTTON
6964 read TBGetBtnStt write TBSetBtnStt;
6965 {* |<#toolbar>
6966 Returns True if toolbar button is marked (highlighted). Allows to
6967 highlight buttons assigning True to this value. }
6969 property TBButtonPressed[ BtnID: Integer ]: Boolean index TB_PRESSBUTTON
6970 read TBGetBtnStt write TBSetBtnStt;
6971 {* |<#toolbar>
6972 Allows to detrmine if toolbar button (given by its command ID) pressed,
6973 and press/unpress it programmatically. }
6975 property TBButtonText[ BtnID: Integer ]: String read TBGetButtonText write TBSetButtonText;
6976 {* |<#toolbar>
6977 Obtains toolbar button text and allows to change it. Be sure that text
6978 is not empty for all buttons, if You want for it to be shown (if at least
6979 one button has empty text, no text labels will be shown at all). At
6980 least set it to ' ' for buttons, which You do not want to show labels,
6981 if You want from other ones to have it. }
6983 property TBButtonImage[ BtnID: Integer ]: Integer read TBGetBtnImgIdx write TBSetBtnImgIdx;
6984 {* |<#toolbar>
6985 Allows to access/change button image. }
6987 property TBButtonRect[ BtnID: Integer ]: TRect read TBGetButtonRect;
6988 {* |<#toolbar>
6989 Obtains rectangle occupied by toolbar button in toolbar window.
6990 (It is not possible to obtain rectangle for buttons, currently
6991 not visible). }
6993 property TBButtonWidth[ BtnID: Integer ]: Integer read TBGetBtnWidth write TBSetBtnWidth;
6994 {* |<#toolbar>
6995 Allows to obtain / change toolbar button width. }
6997 property TBButtonsMinWidth: Integer index 0
6998 {$IFDEF F_P} read TBGetBtMinMaxWidth
6999 {$ELSE DELPHI} read FTBBtMinWidth
7000 {$ENDIF F_P/DELPHI} write TBSetBtMinMaxWidth;
7001 {* |<#toolbar>
7002 Allows to set minimal width for all toolbar buttons. }
7003 property TBButtonsMaxWidth: Integer index 1
7004 {$IFDEF F_P} read TBGetBtMinMaxWidth
7005 {$ELSE DELPHI} read FTBBtMaxWidth
7006 {$ENDIF F_P/DELPHI} write TBSetBtMinMaxWidth;
7007 {* |<#toolbar>
7008 Allows to set maximal width for all toolbar buttons. }
7010 function TBButtonAtPos( X, Y: Integer ): Integer;
7011 {* |<#toolbar>
7012 Returns command ID of button at the given position on toolbar,
7013 or -1, if there are no button at the position. Value 0 is returned
7014 for separators. }
7016 function TBBtnIdxAtPos( X, Y: Integer ): Integer;
7017 {* |<#toolbar>
7018 Returns index of button at the given position on toolbar.
7019 This also can be index of separator button. -1 is returned if
7020 there are no buttons found at the position. }
7022 property TBRows: Integer read TBGetRows write TBSetRows;
7023 {* |<#toolbar>
7024 Returns number of rows for toolbar and allows to try to set
7025 desired number of rows (but system can set another number of
7026 rows in some cases). This property has no effect if tboWrapable
7027 style not present in Options when toolbar is created. }
7029 procedure TBSetTooltips( BtnID1st: Integer; Tooltips: array of PChar );
7030 {* |<#toolbar>
7031 Allows to assign tooltips to several buttons. Until this procedure
7032 is not called, tooltips list is not created and no code is added
7033 to executable. This method of tooltips maintainance for toolbar buttons
7034 is useful both for static and dynamic toolbars (meaning "dynamic" -
7035 toolbars with buttons, deleted and inserted at run-time). }
7037 property OnTBDropDown: TOnEvent read fOnDropDown write fOnDropDown;
7038 {* |<#toolbar>
7039 This event is called for drop down buttons, when user click drop part
7040 of drop down button. To determine for which button event is called,
7041 look at CurItem or CurIndex property. It is also possible to use
7042 common (with combobox) property OnDropDown. }
7044 property OnTBClick: TOnEvent read fOnClick write fOnClick;
7045 {* |<#toolbar>
7046 The same as OnClick. }
7048 //================== RichEdit specific: ==================
7050 property MaxTextSize: DWORD read GetMaxTextSize write SetMaxTextSize;
7051 {* |<#richedit>
7052 This property valid also for simple edit control, not only for RichEdit.
7053 But for usual edit control, maximum text size available is 32K. For
7054 RichEdit, limit is 4Gb. By default, RichEdit is limited to
7055 32767 bytes (to set maximum size available to 2Gb, assign MaxInt value
7056 to a property). Also, to get current text size of RichEdit, use property
7057 TextSize or RE_TextSize[ ]. }
7058 property TextSize: Integer read GetTextSize;
7059 {* |<#richedit>
7060 Common for edit and rich edit controls property, which returns size of
7061 text in edit control. Also, for any other control (or form, or applet
7062 window) returns size (in characters) of Caption or Text (what is, the
7063 same property actually). }
7064 property RE_TextSize[ Units: TRichTextSize ]: Integer read REGetTextSize;
7065 {* |<#richedit>
7066 For RichEdit control, it returns text size, measured in desired units
7067 (rtsChars - characters, including OLE objects, counted as a single
7068 character; rtsBytes - presize length of text image (if it would be stored
7069 in file or stream). Please note, that for RichEdit1.0, only size in
7070 characters can be obtained. }
7071 function RE_TextSizePrecise: Integer;
7072 {* |<#richedit>
7073 By Savva. Returns length of rich edit text. }
7075 property RE_CharFmtArea: TRichFmtArea read fRECharArea write fRECharArea;
7076 {* |<#richedit>
7077 By default, this property is raSelection. Changing it, You determine in
7078 for which area characters format is applyed, when changing
7079 character formatting properties below (not paragraph formatting).
7080 |&A=<a href=#RE_CharFmtArea target=main>%0</a>
7082 property RE_CharFormat: TCharFormat read REGetCharformat write RESetCharFormat;
7083 {* |<#richedit>
7084 In differ to follow properties, which allow to control certain formatting
7085 attributes, this property provides low level access for formatting current
7086 character area (see RE_CharFmtArea). It returns TCharFormat structure,
7087 filled in with formatting attributes, and by assigning another value to
7088 this property You can change desired attributes as You wish. Even if
7089 RichEdit1.0 is used, TCharFormat2 is returned (but extended fields are
7090 ignored for RichEdit1.0). }
7091 property RE_Font: PGraphicTool read REGetFont write RESetFont;
7092 {* |<#richedit>
7093 Font of the first character in current selection (when retrieve).
7094 When set (or subproperties of RE_Font are set), all font attributes are
7095 applied to entire <A area>. To apply only needed attributes, use another
7096 properties: RE_FmtBold, RE_FmtItalic, RE_FmtStrikeout, RE_FmtUnderline,
7097 RE_FmtName, etc.
7098 |<br>
7099 Note, that font size is measured in twips, which is about 1/10 of pixel. }
7100 property RE_FmtBold: Boolean index CFM_BOLD read REGetFontEffects write RESetFontEffect;
7101 {* |<#richedit>
7102 Formatting flag. When retrieve, returns True, if fsBold style RE_Font.FontStyle
7103 is valid for a first character in the selection. When set, changes fsBold
7104 style (True - set, False - reset) for all characters in <A area>. }
7105 property RE_FmtBoldValid: Boolean index CFM_BOLD read REGetFontMask;
7106 {* }
7107 property RE_FmtItalic: Boolean index CFM_ITALIC read REGetFontEffects write RESetFontEffect;
7108 {* |<#richedit>
7109 Formatting flag. Like RE_FmtBold, when retrieving, shows, is fsItalic
7110 style valid for the first character of the selection, and when set, changes
7111 only fsItalic style for an <A area>. }
7112 property RE_FmtItalicValid: Boolean index CFM_ITALIC read REGetFontMask;
7113 {* }
7114 property RE_FmtStrikeout: Boolean index CFM_STRIKEOUT read REGetFontEffects write RESetFontEffect;
7115 {* |<#richedit>
7116 Formatting flag. Like RE_FmtBold, when retrieving, shows, is fsStrikeout
7117 style valid for the first selected character, and when set, changes only
7118 fsStrikeout style for an <A area>. }
7119 property RE_FmtStrikeoutValid: Boolean index CFM_STRIKEOUT read REGetFontMask;
7120 {* }
7121 property RE_FmtUnderline: Boolean index CFM_UNDERLINE read REGetFontEffects write RESetFontEffect;
7122 {* |<#richedit>
7123 Formatting flag. Like RE_FmtBold, when retrieving, shows, is fsUnderline
7124 style valid for the first selected character, and when set, changes
7125 fsUnderline style for an <A area>. }
7126 property RE_FmtUnderlineValid: Boolean index CFM_UNDERLINE read REGetFontMask;
7127 {* }
7128 property RE_FmtUnderlineStyle: TRichUnderline
7129 read REGetUnderlineEx write RESetUnderlineEx;
7130 {* |<#richedit>
7131 Extended underline style. To check, if this property is valid for
7132 entire selection, examine RE_FmtUnderlineValid value. }
7133 property RE_FmtProtected: Boolean index CFM_PROTECTED read REGetFontEffects write RESetFontEffect;
7134 {* |<#richedit>
7135 Formatting flag. When retrieving, shows, is the first character of the selection
7136 is protected from changing it by user (True) or not (False). To get know,
7137 if retrived value is valid for entire selection, check the property
7138 RE_FmtProtectedValid. When set, makes all characters in <A area> protected (
7139 True) or not (False). }
7140 property RE_FmtProtectedValid: Boolean index CFM_PROTECTED read REGetFontMask;
7141 {* |<#richedit>
7142 True, if property RE_FmtProtected is valid for entire selection, when
7143 retrieving it. }
7144 property RE_FmtHidden: Boolean index CFM_HIDDEN read REGetFontEffects write RESetFontEffect;
7145 {* |<#richedit>
7146 For RichEdit3.0, makes text hidden (not displayed). }
7147 property RE_FmtHiddenValid: Boolean index CFM_HIDDEN read REGetFontMask;
7148 {* |<#richedit>
7149 Returns True, if RE_FmtHidden style is valid for entire selection. }
7151 property RE_FmtLink: Boolean index $20 {CFM_LINK} read REGetFontEffects write RESetFontEffect;
7152 {* |<#richedit>
7153 Returns True, if the first selected character is a part of link (URL). }
7154 // by Sergey Shisminzev
7156 property RE_FmtLinkValid: Boolean index $20 {CFM_LINK} read REGetFontMask;
7157 {* }
7158 property RE_FmtFontSize: Integer index (12 shl 16) or CFM_SIZE read REGetFontAttr write RESetFontAttr;
7159 {* |<#richedit>
7160 Formatting value: font size, in twips (1/1440 of an inch, or 1/20 of a
7161 printer's point, or about 1/10 of pixel). When retrieving, returns
7162 RE_Font.FontHeight.
7163 When set, changes font size for entire <A area> (but does not change
7164 other font attributes). }
7165 property RE_FmtFontSizeValid: Boolean read REGetFontSizeValid;
7166 {* |<#richedit>
7167 Returns True, if property RE_FmtFontSize is valid for entire selection,
7168 when retrieving it. }
7169 //property RE_FmtBackColor: Integer index (62 shl 16) or CFM_BACKCOLOR read REGetFontAttr write RESetFontAttr1;
7170 {* |<#richedit>
7171 Background color for an <A area>. }
7172 //property RE_FmtBackColorValid: Boolean index CFM_BACKCOLOR read REGetFontEffect;
7173 {* |<#richedit>
7174 True, if RE_FmtBackColor valid for entire <A area>. }
7175 property RE_FmtAutoBackColor: Boolean index CFM_BACKCOLOR read REGetFontEffects write RESetFontEffect;
7176 {* |<#richedit>
7177 True, when automatic back color is used. }
7178 property RE_FmtAutoBackColorValid: Boolean index CFM_BACKCOLOR read REGetFontMask;
7179 {* }
7180 property RE_FmtFontColor: Integer index (20 shl 16) or CFM_COLOR read REGetFontAttr write RESetFontAttr1;
7181 {* |<#richedit>
7182 Formatting value (font color). When retrieving, returns RE_Font.Color.
7183 When set, changes font color for entire <A area> (but does not change
7184 other font attributes). }
7185 property RE_FmtFontColorValid: Boolean index CFM_COLOR read REGetFontMask;
7186 {* |<#richedit>
7187 Returns True, if property RE_FmtFontColor valid for entire selection,
7188 when retrieving it. }
7189 property RE_FmtAutoColor: Boolean index CFM_COLOR read REGetFontEffects write RESetFontEffect;
7190 {* |<#richedit>
7191 True, when automatic text color is used (in such case, RE_FmtFontColor
7192 assignment is ignored for current area). }
7193 property RE_FmtAutoColorValid: Boolean index CFM_COLOR read REGetFontMask;
7194 {* }
7195 property RE_FmtBackColor: Integer index (64 shl 16) or CFM_BACKCOLOR read REGetFontAttr write RESetFontAttr1;
7196 {* |<#richedit>
7197 Formatting value (back color). Only available for Rich Edit 2.0 and higher.
7198 When set, changes background color for entire <A area> (but does not change
7199 other font attributes). }
7200 property RE_FmtBackColorValid: Boolean index CFM_BACKCOLOR read REGetFontMask;
7201 {* }
7202 property RE_FmtFontOffset: Integer index (16 shl 16) or CFM_OFFSET read REGetFontAttr write RESetFontAttr;
7203 {* |<#richedit>
7204 Formatting value (font vertical offset from baseline, positive values
7205 correspond to subscript). When retrieving, returns offset for first
7206 character in the selection. When set, changes font offset for entire
7207 <A area>. To get know, is retrieved value valid for entire selction,
7208 check RE_FmtFontOffsetValid property. }
7209 property RE_FmtFontOffsetValid: Boolean index CFM_OFFSET read REGetFontMask;
7210 {* |<#richedit>
7211 Returns True, if property RE_FmtFontOffset is valid for entire selection,
7212 when retrieving it. }
7213 property RE_FmtFontCharset: Integer index (25 shl 16) or CFM_CHARSET read REGetFontAttr write RESetFontAttr;
7214 {* |<#richedit>
7215 Returns charset for first character in current selection, when retrieved
7216 (and to get know, if this value is valid for entire selection, check
7217 property RE_FmtFontCharsetValid). When set, changes charset for all
7218 characters in <A area>, but does not alter other formatting attributes. }
7219 property RE_FmtFontCharsetValid: Boolean index CFM_CHARSET read REGetFontMask;
7220 {* |<#richedit>
7221 Returns True, only if rerieved property RE_FmtFontCharset is valid for
7222 entire selection. }
7223 property RE_FmtFontName: String read REGetFontName write RESetFontName;
7224 {* |<#richedit>
7225 Returns font face name for first character in the selection, when retrieved,
7226 and sets font name for entire <A area>, wnen assigned to (without
7227 changing of other formatting attributes). To get know, if retrived
7228 font name valid for entire selection, examine property RE_FmtFontNameValid. }
7229 property RE_FmtFontNameValid: Boolean index CFM_FACE read REGetFontMask;
7230 {* |<#richedit>
7231 Returns True, only if the font name is the same for entire selection,
7232 thus is, if rerieved property value RE_FmtFontName is valid for entire
7233 selection. }
7235 property RE_ParaFmt: TParaFormat read REGetParaFmt write RESetParaFmt;
7236 {* |<#richedit>
7237 Allows to retrieve or set paragraph formatting attributes for currently
7238 selected paragraph(s) in RichEdit control. See also following properties,
7239 which allow to do the same for certain paragraph format attributes
7240 separately. }
7241 property RE_TextAlign: TRichTextAlign read REGetTextAlign write RESetTextAlign;
7242 {* |<#richedit>
7243 Returns text alignment for current selection and allows to change it
7244 (without changing other formatting attributes). }
7245 property RE_TextAlignValid: Boolean index PFM_ALIGNMENT read REGetParaAttrValid;
7246 {* |<#richedit>
7247 Returns True, if property RE_TextAlign is valid for entire selection. If
7248 False, it is concerning only start of selection. }
7249 property RE_Numbering: Boolean read REGetNumbering write RESetNumbering;
7250 {* |<#richedit>
7251 Returns True, if selected text is numbered (or has style of list with
7252 bullets). To get / change numbering style, see properties
7253 RE_NumStyle and RE_NumBrackets. }
7254 property RE_NumStyle: TRichNumbering read REGetNumStyle write RESetNumStyle;
7255 {* |<#richedit>
7256 Advanced numbering style, such as rnArabic etc. If You use it, do not
7257 change RE_Numbering property simultaneously - this can cause changing
7258 style to rnBullets only. }
7259 property RE_NumStart: Integer read REGetNumStart write RESetNumStart;
7260 {* |<#richedit>
7261 Starting number for advanced numbering style. If this property is not
7262 set, numbering is starting by default from 0. For rnLRoman and rnURoman
7263 this cause, that first item has no number to be shown (ancient Roman
7264 people did not invent '0'). }
7265 property RE_NumBrackets: TRichNumBrackets read REGetNumBrackets write RESetNumBrackets;
7266 {* |<#richedit>
7267 Brackets style for advanced numbering. rnbPlain is default
7268 brackets style, and every time, when RE_NumStyle is changed,
7269 RE_NumBrackets is reset to rnbPlain. }
7270 property RE_NumTab: Integer read REGetNumTab write RESetNumTab;
7271 {* |<#richedit>
7272 Tab between start of number and start of paragraph text. If too small too
7273 view number, number is not displayed. (Default value seems to be sufficient
7274 though). }
7275 property RE_NumberingValid: Boolean index PFM_NUMBERING read REGetParaAttrValid;
7276 {* |<#richedit>
7277 Returns True, if RE_Numbering, RE_NumStyle, RE_NumBrackets, RE_NumTab,
7278 RE_NumStart properties are valid for entire selection. }
7279 property RE_Level: Integer read REGetLevel;
7280 {* |<#richedit>
7281 Outline level (for numbering paragraphs?). Read only. }
7282 property RE_SpaceBefore: Integer index 0 or PFM_SPACEBEFORE read REGetSpacing write RESetSpacing;
7283 {* |<#richedit>
7284 Spacing before paragraph. }
7285 property RE_SpaceBeforeValid: Boolean index PFM_SPACEBEFORE read REGetParaAttrValid;
7286 {* |<#richedit>
7287 True, if RE_SpaceBefore value is valid for all selected paragraph (if
7288 False, this value is valid only for first paragraph. }
7289 property RE_SpaceAfter: Integer index 4 or PFM_SPACEAFTER read REGetSpacing write RESetSpacing;
7290 {* |<#richedit>
7291 Spacing after paragraph. }
7292 property RE_SpaceAfterValid: Boolean index PFM_SPACEAFTER read REGetParaAttrValid;
7293 {* |<#richedit>
7294 True, only if RE_SpaceAfter value is valid for all selected paragraphs. }
7295 property RE_LineSpacing: Integer index 8 or PFM_LINESPACING read REGetSpacing write RESetSpacing;
7296 {* |<#richedit>
7297 Linespacing in paragraph (this value is based on RE_SpacingRule property). }
7298 property RE_SpacingRule: Integer read REGetSpacingRule write RESetSpacingRule;
7299 {* |<#richedit>
7300 Linespacing rule. Do not know what is it. }
7301 property RE_LineSpacingValid: Boolean index PFM_LINESPACING read REGetParaAttrValid;
7302 {* |<#richedit>
7303 True, only if RE_LineSpacing and RE_SpacingRule values are valid for
7304 entire selection. }
7305 property RE_Indent: Integer index (20 shl 16) or PFM_OFFSET read REGetParaAttr write RESetParaAttr;
7306 {* |<#richedit>
7307 Returns left indentation for paragraph in current selection and allows
7308 to change it (without changing other formatting attributes). }
7309 property RE_IndentValid: Boolean index PFM_OFFSET read REGetParaAttrValid;
7310 {* |<#richedit>
7311 Returns True, if RE_Indent property is valid for entire selection. }
7312 property RE_StartIndent: Integer index (12 shl 16) or PFM_OFFSETINDENT read REGetParaAttr write RESetParaAttr;
7313 {* |<#richedit>
7314 Returns left indentation for first line in paragraph for current
7315 selection, and allows to change it (without changing other formatting
7316 attributes). }
7317 property RE_StartIndentValid: Boolean read REGetStartIndentValid;
7318 {* |<#richedit>
7319 Returns True, if property RE_StartIndent is valid for entire selection. }
7320 property RE_RightIndent: Integer index (16 shl 16) or PFM_RIGHTINDENT read REGetParaAttr write RESetParaAttr;
7321 {* |<#richedit>
7322 Returns right indent for paragraph in current selection, and allow to
7323 change it (without changing other formatting attributes). }
7324 property RE_RightIndentValid: Boolean index PFM_RIGHTINDENT read REGetParaAttrValid;
7325 {* |<#richedit>
7326 Returns True, if property RE_RightIndent is valid for entire selection only. }
7327 property RE_TabCount: Integer read REGetTabCount write RESetTabCount;
7328 {* |<#richedit>
7329 Number of tab stops in current selection. This value can not be set greater
7330 then MAX_TAB_COUNT (32). }
7331 property RE_Tabs[ Idx: Integer ]: Integer read REGetTabs write RESetTabs;
7332 {* |<#richedit>
7333 Tab stops for RichEdit control. }
7334 property RE_TabsValid: Boolean index PFM_TABSTOPS read REGetParaAttrValid;
7335 {* |<#richedit>
7336 Returns True, if properties RE_Tabs[ ] and RE_TabCount are valid for
7337 entire selection. }
7340 // following does not work now :
7341 property RE_BorderWidth[ Side: TBorderEdge ]: Integer index 2 read REGetBorder write RESetBorder;
7342 { * |<#richedit>
7343 Border width. }
7344 property RE_BorderSpace[ Side: TBorderEdge ]: Integer index 0 read REGetBorder write RESetBorder;
7345 { * |<#richedit>
7346 Border space. }
7347 property RE_BorderStyle[ Side: TBorderEdge ]: Integer index 4 read REGetBorder write RESetBorder;
7348 { * |<#richedit>
7349 Border style. }
7350 property RE_BorderValid: Boolean index PFM_BORDER read REGetParaAttrValid;
7351 { * |<#richedit>
7352 Returns True, if border style, space and width are the same for all
7353 paragraphs in selection. }
7354 property RE_Table: Boolean index $C000 read REGetParaEffect write RESetParaEffect;
7355 { * |<#richedit>
7356 True, if current paragraph is a part of table (row, cell or cell end).
7357 seems working as read only property. }
7358 // end of experiment section
7360 function RE_FmtStandard: PControl;
7361 {* |<#richedit>
7362 "Transparent" method (returns @Self as a result), which (when called)
7363 provides "standard" keyboard interface for formatting Rich text (just
7364 call this method, for example:
7365 ! RichEd1 := NewRichEdit( Panel1, [ ] ).SetAlign( caClient ).RE_FmtStandard;
7366 Following keys will be maintained additionally:
7367 |<pre>
7368 CTRL+I - switch "Italic",
7369 CTRL+B - switch "Bold",
7370 CTRL+U - switch "Underline",
7371 CTRL+SHIFT+U - swith underline type
7372 and turn underline on (note, that some of underline styles
7373 can not be shown properly in RichEdit v2.0 and lower,
7374 though RichEdit2.0 stores data successfully).
7375 CTRL+O - switch "StrikeOut",
7376 CTRL+'gray+' - increase font size,
7377 CTRL+'gray-' - decrease font size,
7378 CTRL+SHIFT+'gray+' - superscript,
7379 CTRL+SHIFT+'gray-' - subscript.
7380 CTRL+SHIFT+Z - ReDo
7381 |</pre>
7382 And, though following standard formatting keys are provided by RichEdit
7383 control itself in Windows2000, some of these are not functioning
7384 automatically in earlier Windows versions, even for RichEdit2.0. So,
7385 functionality of some of these (marked with (*) ) are added here too:
7386 |<pre>
7387 CTRL+L - align paragraph left, (*)
7388 CTRL+R - align paragraph right, (*)
7389 CTRL+E - align paragraph center, (*)
7390 CTRL+A - select all, (*)
7391 double-click on word - select word,
7392 CTRL+Right - to next word,
7393 CTRL+Left - to previous word,
7394 CTRL+Home - to the beginning of text,
7395 CTRL+End - to the end of text.
7396 CTRL+Z - UnDo
7397 |</pre>
7398 If You originally assign some (plain) text to Text property, switching "underline"
7399 can also change other font attributes, e.g., "bold" - if fsBold style is
7400 in default Font. To prevent such behavior, select entire text first (see
7401 SelectAll) and make assignment to RE_Font property, e.g.:
7402 ! RichEd1.SelectAll;
7403 ! RichEd1.RE_Font := RichEd1.RE_Font;
7404 ! RichEd1.SelLength := 0;
7405 |<br>
7406 And, some other notices about formatting. Please remember, that only True
7407 Type fonts can be succefully scaled and transformed to get desired effects
7408 (e.g., bold). By default, RichEdit uses System font face name, which can
7409 even have problems with fsBold style. Please remember also, that assigning
7410 RE_Font to RE_Font just initializying formatting attributes, making all
7411 those valid in entire text, but does not change font attributes. To use
7412 True Type font, directly assign face name You wish, e.g.:
7413 ! RichEd1.SelectAll;
7414 ! RichEd1.RE_Font := RichEd1.RE_Font;
7415 ! RichEd1.RE_Font.FontName := 'Arial';
7416 ! RichEd1.SelLength := 0;
7418 property RE_AutoKeyboard: Boolean index 1 read REGetLangOptions write RESetLangOptions;
7419 {* |<#richedit>
7420 True if autokeyboard on (lovely "feature" of automatic switching keyboard
7421 language when caret is over another language text). For older RichEdit,
7422 is 'on' always, for newest - 'off' by default. }
7424 property RE_OverwriteMode: Boolean read REGetOverwite write RESetOverwrite;
7425 {* |<#richedit>
7426 This property allows to control insert/overwrite mode. First, to examine, if
7427 insert or overwrite mode is current (but it is necessary either to
7428 access this property, at least once, immediately after creating RichEdit
7429 control, or to assign event OnRE_InsOvrMode_Change to your handler).
7430 Second, to set desired mode programmatically - by assigning value to
7431 this property (You also have to initialize monitoring procedure by either
7432 reading RE_OverwriteMode property or assigning handler to event
7433 OnRE_InsOvrMode_Change immediately following RichEdit control creation). }
7434 property OnRE_InsOvrMode_Change: TOnEvent read fOnREInsModeChg write fOnREInsModeChg;
7435 {* |<#richedit>
7436 This event is called, whenever key INSERT is pressed in control (and for
7437 RichEdit, this means, that insert mode is changed). }
7438 property RE_DisableOverwriteChange: Boolean read fReOvrDisable write RESetOvrDisable;
7439 {* |<#richedit>
7440 It is possible to disable switching between "insert" and "overwrite" mode
7441 by user (therefore, event OnRE_InsOvrMode_Change continue works, but it
7442 just called when key INSERT is pressed, though RE_OverwriteMode property
7443 is not actually changed if switching is disabled). }
7445 function RE_LoadFromStream( Stream: PStream; Length: Integer;
7446 Format: TRETextFormat; SelectionOnly: Boolean ): Boolean;
7447 {* |<#richedit>
7448 Use this method rather then assignment to RE_Text property, if
7449 source is stored in file or stream (to minimize resources during
7450 loading of RichEdit content). Data is loading starting from current
7451 position in stream and no more then Length bytes are loaded (use -1
7452 value to load to the end of stream). Loaded data replaces entire
7453 content of RichEdit control, or selection only, depending on SelectionOnly
7454 flag.
7455 |<br>&nbsp;&nbsp;&nbsp;
7456 If You want to provide progress (e.g. in form of progress bar), assign
7457 OnProgress event to your handler - and to examine current position of
7458 loading, read TSream.Position property of soiurce stream). }
7459 function RE_SaveToStream( Stream: PStream; Format: TRETextFormat; SelectionOnly: Boolean ): Boolean;
7460 {* |<#richedit>
7461 Use this method rather then RE_TextProperty to store data to file
7462 or stream (to minimize resources during saving of RichEdit content).
7463 Data is saving starting from current position in a stream (until
7464 end of RichEdit data). If SelectionOnly flag is True, only selected
7465 part of RichEdit text is saved.
7466 |<br>&nbsp;&nbsp;&nbsp;
7467 Like for RE_LoadFromStream, it is possible to assign your method to
7468 OnProgress event (but to calculate progress of save-to-stream operation,
7469 compare current stream position with RE_Size[ rsBytes ] property
7470 value). }
7472 property OnProgress: TOnEvent read fOnProgress write fOnProgress;
7473 {* |<#richedit>
7474 This event is called during RE_SaveToStream, RE_LoadFromStream (and also
7475 during RE_SaveToFile, RE_LoadFromFile and while accessing or changing
7476 RE_Text property). To calculate relative progress, it is possible to
7477 examine current position in stream/file with its total size while reading,
7478 or with rich edit text size, while writing (property RE_TextSize[ rsBytes ]).
7480 function RE_LoadFromFile( const Filename: String; Format: TRETextFormat;
7481 SelectionOnly: Boolean ): Boolean;
7482 {* |<#richedit>
7483 Use this method rather then other assignments to RE_Text property,
7484 if a source for RichEdit is the file. See also RE_LoadFromStream. }
7485 function RE_SaveToFile( const Filename: String; Format: TRETextFormat;
7486 SelectionOnly: Boolean ): Boolean;
7487 {* |<#richedit>
7488 Use this method rather then other similar, if You want to store
7489 entire content of RichEdit or selection only of RichEdit to a file. }
7491 property RE_Text[ Format: TRETextFormat; SelectionOnly: Boolean ]: String read REReadText write REWriteText;
7492 {* |<#richedit>
7493 This property allows to get / replace content of RichEdit control
7494 (entire text or selection only). Using different formats, it is
7495 possible to exclude or replace undesired formatting information
7496 (see TRETextFormat specification). To get or replace entire text
7497 in reText mode (plain text only), it is possible to use habitual
7498 for edit controls Text property.
7499 |<br>&nbsp;&nbsp;&nbsp;
7500 Note: it is possible to append text to the end of RichEdit control
7501 using method Add, but only if property RE_Text is accessed at least
7502 once:
7503 ! RichEdit1.RE_Text[ reText, True ];
7504 (This line can be written immediatelly after creating RichEdit control). }
7506 procedure RE_Append( const S: String; ACanUndo: Boolean );
7507 {* }
7508 procedure RE_InsertRTF( const S: String );
7509 {* }
7510 property RE_Error: Integer read fREError;
7511 {* |<#richedit>
7512 Contains error code, if access to RE_Text failed. }
7514 procedure RE_HideSelection( aHide: Boolean );
7515 {* |<#richedit>
7516 Allows to hide / show selection in RichEdit. }
7518 function RE_SearchText( const Value: String; MatchCase, WholeWord, ScanForward: Boolean;
7519 SearchFrom, SearchTo: Integer ): Integer;
7520 {* |<#richedit>
7521 Searches given string starting from SearchFrom position up to SearchTo
7522 position (to the end of text, if SearchTo is -1). Returns zero-based
7523 character position of the next match, or -1 if there are no more matches.
7524 To search in bacward direction, set ScanForward to False, and pass
7525 SearchFrom > SearchTo (or even SearchFrom = -1 and SearchTo = 0). }
7527 property RE_AutoURLDetect: Boolean read REGetAutoURLDetect write RESetAutoURLDetect;
7528 {* |<#richedit>
7529 If set to True, automatically detects URLs (and highlights it with
7530 blue color, applying fsItalic and fsUnderline font styles (while
7531 typing and loading). Default value is False. Note: if event OnRE_URLClick
7532 or event OnRE_OverURL are set, property RE_AutoURLDetect is set to True
7533 automatically. }
7535 property RE_URL: String read fREUrl;
7536 {* |<#richedit>
7537 Detected URL (valid in OnRE_OverURL and OnRE_URLClick event handlers). }
7538 property OnRE_OverURL: TOnEvent index 0
7539 {$IFDEF F_P} read REGetOnURL
7540 {$ELSE DELPHI} read fOnREOverURL
7541 {$ENDIF F_P/DELPHI} write RESetOnURL;
7542 {* |<#richedit>
7543 Is called when mouse is moving over URL. This can be used to set
7544 cursor, for example, depending on type of URL (to determine URL type
7545 read property RE_URL). }
7546 property OnRE_URLClick: TOnEvent index 8
7547 {$IFDEF F_P} read REGetOnURL
7548 {$ELSE DELPHI} read fOnREURLClick
7549 {$ENDIF F_P/DELPHI} write RESetOnURL;
7550 {* |<#richedit>
7551 Is called when click on URL detected. }
7553 //property RE_SelectionBar: Boolean read REGetSelectionBar write RESetSelectionBar;
7554 //{* ??? - don't know that is this... }
7555 function RE_NoOLEDragDrop: PControl;
7556 {* |<#richedit>
7557 Just prevents drop OLE objects to the rich edit control. Seems not
7558 working for some cases. }
7560 //function RE_Wyswig: PControl;
7562 function RE_Bottomless: PControl;
7563 // not finished
7565 property RE_Transparent: Boolean read REGetTransparent write RESetTransparent;
7566 {* |<#richedit>
7567 Use this property to make richedit control transparent, instead of
7568 Ed_Transparent or Transparent. But do not place such transparent
7569 richedit control directly on form - it can be draw incorrectly when
7570 form is activated and rich editr control is not current active control.
7571 Use at least panel as a parent instead.
7574 //========== both for Edit and RichEdit: =====================
7575 function CanUndo: Boolean;
7576 {* |<#richedit>
7577 |<#edit>
7578 |<#memo>
7579 Returns True, if the edit (or RichEdit) control can correctly process
7580 the EM_UNDO message. }
7581 procedure EmptyUndoBuffer;
7582 {* |<#richedit>
7583 |<#edit>
7584 |<#memo>
7585 Reset the undo flag of an edit control, preventing undoing all previous
7586 changes. }
7587 function Undo: Boolean;
7588 {* |<#richedit>
7589 |<#edit>
7590 |<#memo>
7591 For a single-line edit control, the return value is always TRUE. For a
7592 multiline edit control and RichEdit control, the return value is TRUE if
7593 the undo operation is successful, or FALSE if the undo operation fails. }
7595 function RE_Redo: Boolean;
7596 {* |<#richedit>
7597 Only for RichEdit control: Returns True if successful. }
7599 //----------------------------------------------------------------------
7600 // DateTimePicker
7601 property OnDTPUserString: TDTParseInputEvent read FOnDTPUserString
7602 write FOnDTPUserString;
7603 {* Special event to parse input from the application. Option dtpoParseInput
7604 must be set when control is created. }
7605 property DateTime: TDateTime read GetDateTime write SetDateTime;
7606 {* DateTime for DateTimePicker control only. }
7607 property Date: TDateTime read GetDate write SetDate;
7608 {* Date only for DateTimePicker control only. }
7609 property Time: TDateTime read GetTime write SetTime;
7610 {* Time only for DateTimePicker control only. }
7611 property DateTimeRange: TDateTimeRange read GetDateTimeRange
7612 write SetDateTimeRange;
7613 {* DateTimePicker range. If first date in the agrument assigned is NAN,
7614 minimum system allowed value is used as the left bound, and if the second is
7615 NAN, maximum system allowed is used as the right one. }
7616 property DateTimePickerColors[ Index: TDateTimePickerColor ]: TColor
7617 read GetDateTimePickerColor write SetDateTimePickerColor;
7618 property DateTimeFormat: String write SetDateTimeFormat;
7621 //----------------------------------------------------------------------
7623 //----------------------------------------------------------------------
7624 // ScrollBar
7625 property SBMin: Longint read fSBMinMax.X write SetSBMin;
7626 property SBMax: Longint read fSBMinMax.Y write SetSBMax;
7627 property SBMinMax: TPoint read fSBMinMax write SetSBMinMax;
7628 property SBPosition: Integer read fSBPosition write SetSBPosition;
7629 property SBPageSize: Integer read fSBPageSize write SetSBPageSize;
7631 property OnSBBeforeScroll: TOnSBBeforeScroll read FOnSBBeforeScroll write FOnSBBeforeScroll;
7632 property OnSBScroll: TOnSBScroll read FOnSBScroll write FOnSBScroll;
7634 function SBSetScrollInfo(const SI: TScrollInfo): Integer;
7635 function SBGetScrollInfo(var SI: TScrollInfo): Boolean;
7636 function GetSBMinMax: TPoint;
7637 function GetSBPageSize: Integer;
7638 function GetSBPosition: Integer;
7639 //----------------------------------------------------------------------
7642 // "Through", or "transparent" methods to simplify initial
7643 // adjustment of controls and make non-visual designing of
7644 // forms more easy. All these functions return @Self as a
7645 // result, so, it is possible to use such methods immediately
7646 // in constructing statement, concatenating it with dots, e.g.:
7648 // NewButton( MyForm, 'Click here' ).PlaceUnder.ResizeParentBottom;
7650 function PlaceRight: PControl;
7651 {* Places control right (to previously created on the same parent). }
7652 function PlaceDown: PControl;
7653 {* Places control below (to previously created on the same parent).
7654 Left position is not changed (thus is, kept equal to Parent.Margin). }
7655 function PlaceUnder: PControl;
7656 {* Places control below (to previously created one, aligning its
7657 Left position to Left position of previous control). }
7658 function SetSize( W, H: Integer ): PControl;
7660 {* Changes size of a control. If W or H less or equal to 0,
7661 correspondent size is not changed. }
7662 function Size( W, H: Integer ): PControl;
7663 {* Like SetSize, but provides automatic resizing of parent control
7664 (recursively). Especially useful for aligned controls. }
7665 function SetClientSize( W, H: Integer ): PControl;
7666 {* Like SetSize, but works setting W = ClientWidth, H = ClientHeight.
7667 Use this method for forms, which can not be resized (dialogs). }
7669 function AutoSize( AutoSzOn: Boolean ): PControl;
7671 {* Determines if to autosize control (like label, button, etc.) }
7672 function IsAutoSize: Boolean;
7673 {* TRUE, if a control is autosizing. }
7674 function AlignLeft( P: PControl ): PControl;
7675 {* assigns Left := P.Left }
7676 function AlignTop( P: PControl ): PControl;
7677 {* assigns Top := P.Top }
7678 function ResizeParent: PControl;
7679 {* Resizes parent, calling ResizeParentRight and ResizeParentBottom. }
7680 function ResizeParentRight: PControl;
7681 {* Resizes parent right edge (Margin of parent is added to right
7682 coordinate of a control). If called second time (for the same
7683 parent), resizes only for increasing of right edge of parent. }
7685 function ResizeParentBottom: PControl;
7686 {* Resizes parent bottom edge (Margin of parent is added to
7687 bottom coordinate of a control). }
7688 function CenterOnParent: PControl;
7689 {* Centers control on parent, or if applied to a form, centers
7690 form on screen. }
7692 function Shift( dX, dY : Integer ): PControl;
7693 {* Moves control respectively to current position (Left := Left + dX,
7694 Top := Top + dY). }
7695 function SetPosition( X, Y: Integer ): PControl;
7696 {* Moves control directly to the specified position. }
7698 function Tabulate: PControl;
7699 {* Call it once for form/applet to provide tabulation between controls on
7700 form/on all forms using TAB / SHIFT+TAB and arrow keys. }
7701 function TabulateEx: PControl;
7702 {* Call it once for form/applet to provide tabulation between controls on
7703 form/on all forms using TAB / SHIFT+TAB and arrow keys. Arrow keys are
7704 used more smart, allowing go to nearest control in certain direction. }
7706 function SetAlign( AAlign: TControlAlign ): PControl;
7707 {* Assigns passed value to property Align, aligning control on parent,
7708 and returns @Self (so it is "transparent" function, which can be
7709 used to adjust control at the creation, e.g.:
7710 ! MyLabel := NewLabel( MyForm, 'Label1' ).SetAlign( caBottom );
7711 See also property Align. }
7712 function PreventResizeFlicks: PControl;
7713 {* If called, prevents resizing flicks for child controls, aligned to
7714 right and bottom (but with a lot of code added to executable - about 3,5K).
7715 There is sensible to set DoubleBuffered to True also to eliminate the
7716 most of flicks.
7717 |<br>&nbsp;&nbsp;&nbsp;
7718 This method been applied to a form, prevents, resizing flicks for
7719 form and all controls on the form. If it is called for applet window,
7720 all forms are affected. And if You want, You can apply it for certain
7721 control only - in such case only given control and its children will
7722 be resizing without flicks (e.g., using splitter control). }
7724 property Checked: Boolean read GetChecked write Set_Checked;
7725 {* |<#checkbox>
7726 |<#radiobox>
7727 For checkbox and radiobox - if it is checked. Do not assign
7728 value for radiobox - use SetRadioChecked instead. }
7729 function SetChecked(const Value: Boolean): PControl;
7730 {* |<#checkbox>
7731 Use it to check/uncheck check box control or push button.
7732 Do not apply it to check radio buttons - use SetRadioChecked
7733 method below. }
7734 function SetRadioChecked : PControl;
7735 {* |<#radiobox>
7736 Use it to check radio button item correctly (unchecking all
7737 alternative ones). Actually, method Click is called, and control
7738 itself is returned. }
7739 function SetRadioCheckedOld: PControl;
7740 {* |<#radiobox>
7741 Old version of SetRadioChecked (implemented using recommended API
7742 call. It does not work properly, if control is not visible
7743 (together with its form). }
7744 procedure Click;
7745 {* |<#button>
7746 |<#checkbox>
7747 |<#radiobox>
7748 Emulates click on control programmatically, sending WM_COMMAND
7749 message with BN_CLICKED code. This method is sensible only for
7750 buttons, checkboxes and radioboxes. }
7752 function Perform( msgcode: DWORD; wParam, lParam: Integer): Integer; stdcall;
7753 {* Sends message to control's window (created if needed). }
7754 procedure AttachProc( Proc: TWindowFunc );
7755 {* It is possible to attach dynamically any message handler to window
7756 procedure using this method. Last attached procedure is called first.
7757 If procedure returns True, further processing of a message is stopped.
7758 Attached procedure can be detached using DetachProc (but do not
7759 attach/detach procedures during handling of attached procedure -
7760 this can hang application). }
7761 procedure AttachProcEx( Proc: TWindowFunc; ExecuteAfterAppletTerminated: Boolean );
7762 {* The same as AttachProc, but a handler is executed even after terminating
7763 the main message loop processing (i.e. after assigning true to
7764 AppletTerminated global variable. }
7765 function IsProcAttached( Proc: TWindowFunc ): Boolean;
7766 {* Returns True, if given procedure is already in chain of attached
7767 ones for given control window proc. }
7768 procedure DetachProc( Proc: TWindowFunc );
7769 {* Detaches procedure attached earlier using AttachProc. }
7771 property OnDropFiles: TOnDropFiles read FOnDropFiles write SetOnDropFiles;
7772 {* Assign this event to your handler, if You want to accept drag and drop
7773 files from other applications such as explorer onto your control. When
7774 this event is assigned to a control or form, this has effect also for
7775 all its child controls too. }
7777 property CustomData: Pointer read fCustomData write fCustomData;
7778 {* Can be used to exend the object when new type of control added. Memory,
7779 pointed by this pointer, released automatically in the destructor. }
7780 property CustomObj: PObj read fCustomObj write fCustomObj;
7781 {* Can be used to exend the object when new type of control added. Object,
7782 pointed by this pointer, released automatically in the destructor. }
7783 procedure SetAutoPopupMenu( PopupMenu: PObj );
7784 {* To assign a popup menu to the control, call SetAutoPopupMenu method of
7785 the control with popup menu object as a parameter. }
7787 function SupportMnemonics: PControl;
7788 {* This method provides supporting mnemonic keys in menus, buttons, checkboxes,
7789 toolbar buttons. }
7790 property OnScroll: TOnScroll read FOnScroll write SetOnScroll;
7791 {* }
7795 {$IFDEF USE_CONSTRUCTORS}
7796 //------------------------------------------------------------
7797 // constructors here:
7798 constructor CreateWindowed( AParent: PControl; AClassName: PChar; ACtl3D: Boolean );
7799 constructor CreateApplet( const ACaption: String );
7800 constructor CreateForm( AParent: PControl; const ACaption: String );
7801 constructor CreateControl( AParent: PControl; AClassName: PChar; AStyle: DWORD;
7802 ACtl3D: Boolean; Actions: PCommandActions );
7803 constructor CreateButton( AParent: PControl; const ACaption: String );
7804 constructor CreateBitBtn( AParent: PControl; const ACaption: String;
7805 AOptions: TBitBtnOptions; ALayout: TGlyphLayout; AGlyphBitmap: HBitmap;
7806 AGlyphCount: Integer);
7807 constructor CreateLabel( AParent: PControl; const ACaption: String );
7808 constructor CreateWordWrapLabel( AParent: PControl; const ACaption: String );
7809 constructor CreateLabelEffect( AParent: PControl; ACaption: String; AShadowDeep: Integer );
7810 constructor CreatePaintBox( AParent: PControl );
7811 constructor CreateGradientPanel( AParent: PControl; AColor1, AColor2: TColor );
7812 constructor CreateGradientPanelEx( AParent: PControl; AColor1, AColor2: TColor;
7813 AStyle: TGradientStyle; ALayout: TGradientLayout );
7814 constructor CreateGroupbox( AParent: PControl; const ACaption: String );
7815 constructor CreateCheckbox( AParent: PControl; const ACaption: String );
7816 constructor CreateRadiobox( AParent: PControl; const ACaption: String );
7817 constructor CreateEditbox( AParent: PControl; AOptions: TEditOptions );
7818 constructor CreatePanel( AParent: PControl; AStyle: TEdgeStyle );
7819 constructor CreateSplitter( AParent: PControl; AMinSizePrev, AMinSizeNext: Integer;
7820 EdgeStyle: TEdgeStyle );
7821 constructor CreateListbox( AParent: PControl; AOptions: TListOptions );
7822 constructor CreateCombobox( AParent: PControl; AOptions: TComboOptions );
7823 constructor CreateCommonControl( AParent: PControl; AClassName: PChar; AStyle: DWORD;
7824 ACtl3D: Boolean; Actions: PCommandActions );
7825 constructor CreateRichEdit( AParent: PControl; AOptions: TEditOptions );
7826 constructor CreateRichEdit1( AParent: PControl; AOptions: TEditOptions );
7827 constructor CreateProgressbar( AParent: PControl );
7828 constructor CreateProgressbarEx( AParent: PControl; AOptions: TProgressbarOptions );
7829 constructor CreateListView( AParent: PControl; AStyle: TListViewStyle; AOptions: TListViewOptions;
7830 AImageListSmall, AImageListNormal, AImageListState: PImageList );
7831 constructor CreateTreeView( AParent: PControl; AOptions: TTreeViewOptions;
7832 AImgListNormal, AImgListState: PImageList );
7833 constructor CreateTabControl( AParent: PControl; ATabs: array of String;
7834 AOptions: TTabControlOptions; AImgList: PImageList; AImgList1stIdx: Integer );
7835 constructor CreateToolbar( AParent: PControl; AAlign: TControlAlign; AOptions: TToolbarOptions;
7836 ABitmap: HBitmap; AButtons: array of PChar;
7837 ABtnImgIdxArray: array of Integer );
7838 {$ENDIF USE_CONSTRUCTORS}
7840 {$IFDEF USE_CUSTOMEXTENSIONS}
7841 {$I CUSTOM_TCONTROL_EXTENSION.inc}
7842 {$ENDIF}
7843 // If an option USE_CUSTOMEXTENSIONS is enabled (at the beginning of this
7844 // unit), You can freely extend TControl definition by your own fields,
7845 // methods and properties. This provides You with capability to extend
7846 // TControl implementing another kinds of visual controls without deriving
7847 // new descendant objects from TControl. This way is provided to avoid too
7848 // large grow of executable size. You also can derive your own controls
7849 // from TControl using standard OOP capabilities. In such case an option
7850 // USE_CONSTRUCTORS should be turned on (see it at the start of this unit).
7851 // If You choose this "flat" model of extending the TControl with your
7852 // own properties, fieds, methods, events, etc. You should provide three
7853 // inc-files: CUSTOM_TCONTROL_EXTENSION.inc, containing such definitions
7854 // for TControl, CUSTOM_KOL_EXTENSION.inc, containing needed global
7855 // declarations, and CUSTOM_CODE_EXTENSION.inc, the implementation of those
7856 // two.
7857 // Because KOL is always grow and constantly is extending by me, I also can
7858 // add my own complements for TControl. To avoid naming conflicts, I suggest
7859 // to use the same naming rule for all of You. Name your fields, properies, etc.
7860 // using a form idx_SomeName, where idx is a prefix, containing several
7861 // (at least one) letters and digits. E.g. ZK65_OnSomething.
7863 protected
7864 {$IFDEF USE_DROPDOWNCOUNT}
7865 fDropDownCount: Cardinal;
7866 {$ENDIF}
7867 public
7868 {$IFDEF USE_DROPDOWNCOUNT}
7869 property DropDownCount: Cardinal read fDropDownCount write fDropDownCount;
7870 {$ENDIF}
7871 end;
7872 //[END OF TControl DEFINITION]
7874 {$IFDEF USE_MHTOOLTIP}
7875 {$DEFINE interface}
7876 {$I KOLMHToolTip}
7877 {$UNDEF interface}
7878 {$ENDIF}
7880 //[Paint Background PROCEDURE]
7881 type
7882 TOnPaintBkgnd = procedure( Sender: PControl; DC: HDC; Rect: PRect );
7883 {* Global event definition. Used to define Global_OnPaintBackground
7884 event placeholder. }
7886 procedure DefaultPaintBackground( Sender: PControl; DC: HDC; Rect: PRect );
7889 Global_OnPaintBkgnd: TOnPaintBkgnd = DefaultPaintBackground;
7890 {* Global event. It is assigned in XBackgounds.pas add-on to replace
7891 PaintBackground method for all TVisual objects, allowing great
7892 visualization effect: transparent controls over [animated] bitmap
7893 background. Idea:
7894 | <a href=mailto:"bw@sunv.com">Wei&nbsp;Bao</a>. Implementation:
7895 | <a href=mailto:"bonanzas@xcl.cjb.net">Kladov&nbsp;Vladimir</a>. }
7897 procedure DummyPaintProc( Sender: PControl; DC: HDC );
7899 //[GetShiftState DECLARATION]
7900 function GetShiftState: DWORD;
7902 //[WndProcXXX DECLARATIONS]
7903 function WndProcMouse( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
7904 function WndProcKeybd( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
7905 function WndProcDummy( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
7906 function WndProcBufferedDraw( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
7907 {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}
7908 function WndProcBtnReturnClick( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
7909 {$ENDIF}
7911 //[InitCommonXXXX DECLARATIONS]
7912 procedure InitCommonControlSizeNotify( Ctrl: PControl );
7913 procedure InitCommonControlCommonNotify( Ctrl: PControl );
7915 //[Buffered Draw DECLARATIONS]
7917 Global_OnBufferedDraw: function( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean
7918 = WndProcDummy;
7919 Global_DblBufCreateWnd: procedure( Sender: PObj ) = DummyObjProc;
7920 Global_Invalidate: procedure( Sender: PObj ) = DummyObjProc;
7921 {* Is called in TControl.Invalidate to extend it in case when DoubleBuffered
7922 painting used. }
7924 Global_TranspDrawBkgnd: procedure( DC: HDC; Sender: PControl );
7926 //Global_OnCreateWindow: procedure( Sender: PObj ) = DummyObjProc;
7927 //{* Is called when TControl object is created. }
7928 //Global_OnDestroyWindow: procedure( Sender: PObj ) = DummyObjProc;
7929 //{* Is called before destroying TControl object (after accepting it,
7930 // if event OnClose is defined). }
7931 Global_OnBeginPaint: procedure( Sender: PControl; DC: HDC ) = DummyPaintProc;
7932 {* Is called before painting a window. }
7933 Global_OnEndPaint: procedure( Sender: PControl; DC: HDC ) = DummyPaintProc;
7934 {* Is called after painting a window. }
7935 HelpFilePath: PChar;
7936 {* Path to application help file. If not assigned, application path with
7937 extension replaced to '.hlp' used. To use '.chm' file (HtmlHelp),
7938 call AssignHtmlHelp with a path to a html help file (or a name). }
7940 //[Html Help DECLARATIONS]
7941 procedure AssignHtmlHelp( const HtmlHelpPath: String );
7942 procedure HtmlHelpCommand( Wnd: HWnd; const HelpFilePath: String; Cmd, Data: Integer );
7943 {* Use this wrapper procedure to call HtmlHelp API function. }
7944 //+++++++++++ HTML HELP DEFINITIONS SECTION:
7945 // this section is from
7946 // HTML Help API Interface Unit
7947 // Copyright (c) 1999 The Helpware Group
7948 // provided for KOL by Alexey Babenko
7949 const
7950 HH_DISPLAY_TOPIC = $0000; {**}
7951 HH_HELP_FINDER = $0000; // WinHelp equivalent
7952 HH_DISPLAY_TOC = $0001; // not currently implemented
7953 HH_DISPLAY_INDEX = $0002; // not currently implemented
7954 HH_DISPLAY_SEARCH = $0003; // not currently implemented
7955 HH_SET_WIN_TYPE = $0004;
7956 HH_GET_WIN_TYPE = $0005;
7957 HH_GET_WIN_HANDLE = $0006;
7958 HH_ENUM_INFO_TYPE = $0007; // Get Info type name, call repeatedly to enumerate, -1 at end
7959 HH_SET_INFO_TYPE = $0008; // Add Info type to filter.
7960 HH_SYNC = $0009;
7961 HH_RESERVED1 = $000A;
7962 HH_RESERVED2 = $000B;
7963 HH_RESERVED3 = $000C;
7964 HH_KEYWORD_LOOKUP = $000D;
7965 HH_DISPLAY_TEXT_POPUP = $000E; // display string resource id or text in a popup window
7966 HH_HELP_CONTEXT = $000F; {**}// display mapped numeric value in dwData
7967 HH_TP_HELP_CONTEXTMENU = $0010; // text popup help, same as WinHelp HELP_CONTEXTMENU
7968 HH_TP_HELP_WM_HELP = $0011; // text popup help, same as WinHelp HELP_WM_HELP
7969 HH_CLOSE_ALL = $0012; // close all windows opened directly or indirectly by the caller
7970 HH_ALINK_LOOKUP = $0013; // ALink version of HH_KEYWORD_LOOKUP
7971 HH_GET_LAST_ERROR = $0014; // not currently implemented // See HHERROR.h
7972 HH_ENUM_CATEGORY = $0015; // Get category name, call repeatedly to enumerate, -1 at end
7973 HH_ENUM_CATEGORY_IT = $0016; // Get category info type members, call repeatedly to enumerate, -1 at end
7974 HH_RESET_IT_FILTER = $0017; // Clear the info type filter of all info types.
7975 HH_SET_INCLUSIVE_FILTER = $0018; // set inclusive filtering method for untyped topics to be included in display
7976 HH_SET_EXCLUSIVE_FILTER = $0019; // set exclusive filtering method for untyped topics to be excluded from display
7977 HH_INITIALIZE = $001C; // Initializes the help system.
7978 HH_UNINITIALIZE = $001D; // Uninitializes the help system.
7979 HH_PRETRANSLATEMESSAGE = $00fd; // Pumps messages. (NULL, NULL, MSG*).
7980 HH_SET_GLOBAL_PROPERTY = $00fc; // Set a global property. (NULL, NULL, HH_GPROP)
7982 { window properties }
7984 const
7985 HHWIN_PROP_TAB_AUTOHIDESHOW = $00000001; // (1 << 0) Automatically hide/show tri-pane window
7986 HHWIN_PROP_ONTOP = $00000002; // (1 << 1) Top-most window
7987 HHWIN_PROP_NOTITLEBAR = $00000004; // (1 << 2) no title bar
7988 HHWIN_PROP_NODEF_STYLES = $00000008; // (1 << 3) no default window styles (only HH_WINTYPE.dwStyles)
7989 HHWIN_PROP_NODEF_EXSTYLES = $00000010; // (1 << 4) no default extended window styles (only HH_WINTYPE.dwExStyles)
7990 HHWIN_PROP_TRI_PANE = $00000020; // (1 << 5) use a tri-pane window
7991 HHWIN_PROP_NOTB_TEXT = $00000040; // (1 << 6) no text on toolbar buttons
7992 HHWIN_PROP_POST_QUIT = $00000080; // (1 << 7) post WM_QUIT message when window closes
7993 HHWIN_PROP_AUTO_SYNC = $00000100; // (1 << 8) automatically ssync contents and index
7994 HHWIN_PROP_TRACKING = $00000200; // (1 << 9) send tracking notification messages
7995 HHWIN_PROP_TAB_SEARCH = $00000400; // (1 << 10) include search tab in navigation pane
7996 HHWIN_PROP_TAB_HISTORY = $00000800; // (1 << 11) include history tab in navigation pane
7997 HHWIN_PROP_TAB_FAVORITES = $00001000; // (1 << 12) include favorites tab in navigation pane
7998 HHWIN_PROP_CHANGE_TITLE = $00002000; // (1 << 13) Put current HTML title in title bar
7999 HHWIN_PROP_NAV_ONLY_WIN = $00004000; // (1 << 14) Only display the navigation window
8000 HHWIN_PROP_NO_TOOLBAR = $00008000; // (1 << 15) Don't display a toolbar
8001 HHWIN_PROP_MENU = $00010000; // (1 << 16) Menu
8002 HHWIN_PROP_TAB_ADVSEARCH = $00020000; // (1 << 17) Advanced FTS UI.
8003 HHWIN_PROP_USER_POS = $00040000; // (1 << 18) After initial creation, user controls window size/position
8004 HHWIN_PROP_TAB_CUSTOM1 = $00080000; // (1 << 19) Use custom tab #1
8005 HHWIN_PROP_TAB_CUSTOM2 = $00100000; // (1 << 20) Use custom tab #2
8006 HHWIN_PROP_TAB_CUSTOM3 = $00200000; // (1 << 21) Use custom tab #3
8007 HHWIN_PROP_TAB_CUSTOM4 = $00400000; // (1 << 22) Use custom tab #4
8008 HHWIN_PROP_TAB_CUSTOM5 = $00800000; // (1 << 23) Use custom tab #5
8009 HHWIN_PROP_TAB_CUSTOM6 = $01000000; // (1 << 24) Use custom tab #6
8010 HHWIN_PROP_TAB_CUSTOM7 = $02000000; // (1 << 25) Use custom tab #7
8011 HHWIN_PROP_TAB_CUSTOM8 = $04000000; // (1 << 26) Use custom tab #8
8012 HHWIN_PROP_TAB_CUSTOM9 = $08000000; // (1 << 27) Use custom tab #9
8013 HHWIN_TB_MARGIN = $10000000; // (1 << 28) the window type has a margin
8015 { window parameters }
8017 const
8018 HHWIN_PARAM_PROPERTIES = $00000002; // (1 << 1) valid fsWinProperties
8019 HHWIN_PARAM_STYLES = $00000004; // (1 << 2) valid dwStyles
8020 HHWIN_PARAM_EXSTYLES = $00000008; // (1 << 3) valid dwExStyles
8021 HHWIN_PARAM_RECT = $00000010; // (1 << 4) valid rcWindowPos
8022 HHWIN_PARAM_NAV_WIDTH = $00000020; // (1 << 5) valid iNavWidth
8023 HHWIN_PARAM_SHOWSTATE = $00000040; // (1 << 6) valid nShowState
8024 HHWIN_PARAM_INFOTYPES = $00000080; // (1 << 7) valid apInfoTypes
8025 HHWIN_PARAM_TB_FLAGS = $00000100; // (1 << 8) valid fsToolBarFlags
8026 HHWIN_PARAM_EXPANSION = $00000200; // (1 << 9) valid fNotExpanded
8027 HHWIN_PARAM_TABPOS = $00000400; // (1 << 10) valid tabpos
8028 HHWIN_PARAM_TABORDER = $00000800; // (1 << 11) valid taborder
8029 HHWIN_PARAM_HISTORY_COUNT = $00001000; // (1 << 12) valid cHistory
8030 HHWIN_PARAM_CUR_TAB = $00002000; // (1 << 13) valid curNavType
8032 { button constants }
8034 const
8035 HHWIN_BUTTON_EXPAND = $00000002; // (1 << 1) Expand/contract button
8036 HHWIN_BUTTON_BACK = $00000004; // (1 << 2) Back button
8037 HHWIN_BUTTON_FORWARD = $00000008; // (1 << 3) Forward button
8038 HHWIN_BUTTON_STOP = $00000010; // (1 << 4) Stop button
8039 HHWIN_BUTTON_REFRESH = $00000020; // (1 << 5) Refresh button
8040 HHWIN_BUTTON_HOME = $00000040; // (1 << 6) Home button
8041 HHWIN_BUTTON_BROWSE_FWD = $00000080; // (1 << 7) not implemented
8042 HHWIN_BUTTON_BROWSE_BCK = $00000100; // (1 << 8) not implemented
8043 HHWIN_BUTTON_NOTES = $00000200; // (1 << 9) not implemented
8044 HHWIN_BUTTON_CONTENTS = $00000400; // (1 << 10) not implemented
8045 HHWIN_BUTTON_SYNC = $00000800; // (1 << 11) Sync button
8046 HHWIN_BUTTON_OPTIONS = $00001000; // (1 << 12) Options button
8047 HHWIN_BUTTON_PRINT = $00002000; // (1 << 13) Print button
8048 HHWIN_BUTTON_INDEX = $00004000; // (1 << 14) not implemented
8049 HHWIN_BUTTON_SEARCH = $00008000; // (1 << 15) not implemented
8050 HHWIN_BUTTON_HISTORY = $00010000; // (1 << 16) not implemented
8051 HHWIN_BUTTON_FAVORITES = $00020000; // (1 << 17) not implemented
8052 HHWIN_BUTTON_JUMP1 = $00040000; // (1 << 18)
8053 HHWIN_BUTTON_JUMP2 = $00080000; // (1 << 19)
8054 HHWIN_BUTTON_ZOOM = $00100000; // (1 << 20)
8055 HHWIN_BUTTON_TOC_NEXT = $00200000; // (1 << 21)
8056 HHWIN_BUTTON_TOC_PREV = $00400000; // (1 << 22)
8058 HHWIN_DEF_BUTTONS = (HHWIN_BUTTON_EXPAND
8059 OR HHWIN_BUTTON_BACK
8060 OR HHWIN_BUTTON_OPTIONS
8061 OR HHWIN_BUTTON_PRINT);
8064 { Button IDs }
8066 const
8067 IDTB_EXPAND = 200;
8068 IDTB_CONTRACT = 201;
8069 IDTB_STOP = 202;
8070 IDTB_REFRESH = 203;
8071 IDTB_BACK = 204;
8072 IDTB_HOME = 205;
8073 IDTB_SYNC = 206;
8074 IDTB_PRINT = 207;
8075 IDTB_OPTIONS = 208;
8076 IDTB_FORWARD = 209;
8077 IDTB_NOTES = 210; // not implemented
8078 IDTB_BROWSE_FWD = 211;
8079 IDTB_BROWSE_BACK = 212;
8080 IDTB_CONTENTS = 213; // not implemented
8081 IDTB_INDEX = 214; // not implemented
8082 IDTB_SEARCH = 215; // not implemented
8083 IDTB_HISTORY = 216; // not implemented
8084 IDTB_FAVORITES = 217; // not implemented
8085 IDTB_JUMP1 = 218;
8086 IDTB_JUMP2 = 219;
8087 IDTB_CUSTOMIZE = 221;
8088 IDTB_ZOOM = 222;
8089 IDTB_TOC_NEXT = 223;
8090 IDTB_TOC_PREV = 224;
8093 { Notification codes }
8095 const
8096 HHN_FIRST = (0-860);
8097 HHN_LAST = (0-879);
8099 HHN_NAVCOMPLETE = (HHN_FIRST-0);
8100 HHN_TRACK = (HHN_FIRST-1);
8101 HHN_WINDOW_CREATE = (HHN_FIRST-2);
8104 type
8105 {*** Used by command HH_GET_LAST_ERROR
8106 NOTE: Not part of the htmlhelp.h but documented in HH Workshop help
8107 You must call SysFreeString(xx.description) to free BSTR
8109 tagHH_LAST_ERROR = packed record
8110 cbStruct: Integer; // sizeof this structure
8111 hr: Integer; // Specifies the last error code.
8112 description: PWideChar; // (BSTR) Specifies a Unicode string containing a description of the error.
8113 end;
8114 HH_LAST_ERROR = tagHH_LAST_ERROR;
8115 THHLastError = tagHH_LAST_ERROR;
8118 type
8119 {*** Notify event info for HHN_NAVCOMPLETE, HHN_WINDOW_CREATE }
8120 PHHNNotify = ^THHNNotify;
8121 tagHHN_NOTIFY = packed record
8122 hdr: TNMHdr;
8123 pszUrl: PChar; //PCSTR: Multi-byte, null-terminated string
8124 end;
8125 HHN_NOTIFY = tagHHN_NOTIFY;
8126 THHNNotify = tagHHN_NOTIFY;
8128 {** Use by command HH_DISPLAY_TEXT_POPUP}
8129 PHHPopup = ^THHPopup;
8130 tagHH_POPUP = packed record
8131 cbStruct: Integer; // sizeof this structure
8132 hinst: HINST; // instance handle for string resource
8133 idString: cardinal; // string resource id, or text id if pszFile is specified in HtmlHelp call
8134 pszText: PChar; // used if idString is zero
8135 pt: TPOINT; // top center of popup window
8136 clrForeground: COLORREF; // use -1 for default
8137 clrBackground: COLORREF; // use -1 for default
8138 rcMargins: TRect; // amount of space between edges of window and text, -1 for each member to ignore
8139 pszFont: PChar; // facename, point size, char set, BOLD ITALIC UNDERLINE
8140 end;
8141 HH_POPUP = tagHH_POPUP;
8142 THHPopup = tagHH_POPUP;
8144 {** Use by commands - HH_ALINK_LOOKUP, HH_KEYWORD_LOOKUP}
8145 PHHAKLink = ^THHAKLink;
8146 tagHH_AKLINK = packed record
8147 cbStruct: integer; // sizeof this structure
8148 fReserved: BOOL; // must be FALSE (really!)
8149 pszKeywords: PChar; // semi-colon separated keywords
8150 pszUrl: PChar; // URL to jump to if no keywords found (may be NULL)
8151 pszMsgText: PChar; // Message text to display in MessageBox if pszUrl is NULL and no keyword match
8152 pszMsgTitle: PChar; // Message text to display in MessageBox if pszUrl is NULL and no keyword match
8153 pszWindow: PChar; // Window to display URL in
8154 fIndexOnFail: BOOL; // Displays index if keyword lookup fails.
8155 end;
8156 HH_AKLINK = tagHH_AKLINK;
8157 THHAKLink = tagHH_AKLINK;
8160 const
8161 HHWIN_NAVTYPE_TOC = 0;
8162 HHWIN_NAVTYPE_INDEX = 1;
8163 HHWIN_NAVTYPE_SEARCH = 2;
8164 HHWIN_NAVTYPE_FAVORITES = 3;
8165 HHWIN_NAVTYPE_HISTORY = 4; // not implemented
8166 HHWIN_NAVTYPE_AUTHOR = 5;
8167 HHWIN_NAVTYPE_CUSTOM_FIRST = 11;
8170 const
8171 IT_INCLUSIVE = 0;
8172 IT_EXCLUSIVE = 1;
8173 IT_HIDDEN = 2;
8175 type
8176 PHHEnumIT = ^THHEnumIT;
8177 tagHH_ENUM_IT = packed record //tagHH_ENUM_IT, HH_ENUM_IT, *PHH_ENUM_IT
8178 cbStruct: Integer; // size of this structure
8179 iType: Integer; // the type of the information type ie. Inclusive, Exclusive, or Hidden
8180 pszCatName: PAnsiChar; // Set to the name of the Category to enumerate the info types in a category; else NULL
8181 pszITName: PAnsiChar; // volitile pointer to the name of the infotype. Allocated by call. Caller responsible for freeing
8182 pszITDescription: PAnsiChar; // volitile pointer to the description of the infotype.
8183 end;
8184 THHEnumIT = tagHH_ENUM_IT;
8187 type
8188 PHHEnumCat = ^THHEnumCat;
8189 tagHH_ENUM_CAT = packed record //tagHH_ENUM_CAT, HH_ENUM_CAT, *PHH_ENUM_CAT
8190 cbStruct: Integer; // size of this structure
8191 pszCatName: PAnsiChar; // volitile pointer to the category name
8192 pszCatDescription: PAnsiChar; // volitile pointer to the category description
8193 end;
8194 THHEnumCat = tagHH_ENUM_CAT;
8197 type
8198 PHHSetInfoType = ^THHSetInfoType;
8199 tagHH_SET_INFOTYPE = packed record //tagHH_SET_INFOTYPE, HH_SET_INFOTYPE, *PHH_SET_INFOTYPE
8200 cbStruct: Integer; // the size of this structure
8201 pszCatName: PAnsiChar; // the name of the category, if any, the InfoType is a member of.
8202 pszInfoTypeName: PAnsiChar; // the name of the info type to add to the filter
8203 end;
8204 THHSetInfoType = tagHH_SET_INFOTYPE;
8207 type
8208 HH_INFOTYPE = DWORD;
8209 THHInfoType = HH_INFOTYPE;
8210 PHHInfoType = ^THHInfoType; //PHH_INFOTYPE
8213 const
8214 HHWIN_NAVTAB_TOP = 0;
8215 HHWIN_NAVTAB_LEFT = 1;
8216 HHWIN_NAVTAB_BOTTOM = 2;
8218 const
8219 HH_MAX_TABS = 19; // maximum number of tabs
8220 const
8221 HH_TAB_CONTENTS = 0;
8222 HH_TAB_INDEX = 1;
8223 HH_TAB_SEARCH = 2;
8224 HH_TAB_FAVORITES = 3;
8225 HH_TAB_HISTORY = 4;
8226 HH_TAB_AUTHOR = 5;
8227 HH_TAB_CUSTOM_FIRST = 11;
8228 HH_TAB_CUSTOM_LAST = HH_MAX_TABS;
8230 HH_MAX_TABS_CUSTOM = (HH_TAB_CUSTOM_LAST - HH_TAB_CUSTOM_FIRST + 1);
8234 { HH_DISPLAY_SEARCH Command Related Structures and Constants }
8236 const
8237 HH_FTS_DEFAULT_PROXIMITY = (-1);
8239 type
8240 {** Used by command HH_DISPLAY_SEARCH}
8241 PHHFtsQuery = ^THHFtsQuery;
8242 tagHH_FTS_QUERY = packed record //tagHH_FTS_QUERY, HH_FTS_QUERY
8243 cbStruct: integer; // Sizeof structure in bytes.
8244 fUniCodeStrings: BOOL; // TRUE if all strings are unicode.
8245 pszSearchQuery: PChar; // String containing the search query.
8246 iProximity: LongInt; // Word proximity.
8247 fStemmedSearch: Bool; // TRUE for StemmedSearch only.
8248 fTitleOnly: Bool; // TRUE for Title search only.
8249 fExecute: Bool; // TRUE to initiate the search.
8250 pszWindow: PChar; // Window to display in
8251 end;
8252 THHFtsQuery = tagHH_FTS_QUERY;
8255 { HH_WINTYPE Structure }
8257 type
8258 {** Used by commands HH_GET_WIN_TYPE, HH_SET_WIN_TYPE}
8259 PHHWinType = ^THHWinType;
8260 tagHH_WINTYPE = packed record //tagHH_WINTYPE, HH_WINTYPE, *PHH_WINTYPE;
8261 cbStruct: Integer; // IN: size of this structure including all Information Types
8262 fUniCodeStrings: BOOL; // IN/OUT: TRUE if all strings are in UNICODE
8263 pszType: PChar; // IN/OUT: Name of a type of window
8264 fsValidMembers: DWORD; // IN: Bit flag of valid members (HHWIN_PARAM_)
8265 fsWinProperties: DWORD; // IN/OUT: Properties/attributes of the window (HHWIN_)
8267 pszCaption: PChar; // IN/OUT: Window title
8268 dwStyles: DWORD; // IN/OUT: Window styles
8269 dwExStyles: DWORD; // IN/OUT: Extended Window styles
8270 rcWindowPos: TRect; // IN: Starting position, OUT: current position
8271 nShowState: Integer; // IN: show state (e.g., SW_SHOW)
8273 hwndHelp: HWND; // OUT: window handle
8274 hwndCaller: HWND; // OUT: who called this window
8276 paInfoTypes: PHHInfoType; // IN: Pointer to an array of Information Types
8278 { The following members are only valid if HHWIN_PROP_TRI_PANE is set }
8280 hwndToolBar: HWND; // OUT: toolbar window in tri-pane window
8281 hwndNavigation: HWND; // OUT: navigation window in tri-pane window
8282 hwndHTML: HWND; // OUT: window displaying HTML in tri-pane window
8283 iNavWidth: Integer; // IN/OUT: width of navigation window
8284 rcHTML: TRect; // OUT: HTML window coordinates
8286 pszToc: PChar; // IN: Location of the table of contents file
8287 pszIndex: PChar; // IN: Location of the index file
8288 pszFile: PChar; // IN: Default location of the html file
8289 pszHome: PChar; // IN/OUT: html file to display when Home button is clicked
8290 fsToolBarFlags: DWORD; // IN: flags controling the appearance of the toolbar (HHWIN_BUTTON_)
8291 fNotExpanded: BOOL; // IN: TRUE/FALSE to contract or expand, OUT: current state
8292 curNavType: Integer; // IN/OUT: UI to display in the navigational pane
8293 tabpos: Integer; // IN/OUT: HHWIN_NAVTAB_TOP, HHWIN_NAVTAB_LEFT, or HHWIN_NAVTAB_BOTTOM
8294 idNotify: Integer; // IN: ID to use for WM_NOTIFY messages
8295 tabOrder: packed array[0..HH_MAX_TABS] of Byte; // IN/OUT: tab order: Contents, Index, Search, History, Favorites, Reserved 1-5, Custom tabs
8296 cHistory: Integer; // IN/OUT: number of history items to keep (default is 30)
8297 pszJump1: PChar; // Text for HHWIN_BUTTON_JUMP1
8298 pszJump2: PChar; // Text for HHWIN_BUTTON_JUMP2
8299 pszUrlJump1: PChar; // URL for HHWIN_BUTTON_JUMP1
8300 pszUrlJump2: PChar; // URL for HHWIN_BUTTON_JUMP2
8301 rcMinSize: TRect; // Minimum size for window (ignored in version 1)
8303 cbInfoTypes: Integer; // size of paInfoTypes;
8304 pszCustomTabs: PChar; // multiple zero-terminated strings
8305 end;
8306 HH_WINTYPE = tagHH_WINTYPE;
8307 THHWinType = tagHH_WINTYPE;
8309 const
8310 HHACT_TAB_CONTENTS = 0;
8311 HHACT_TAB_INDEX = 1;
8312 HHACT_TAB_SEARCH = 2;
8313 HHACT_TAB_HISTORY = 3;
8314 HHACT_TAB_FAVORITES = 4;
8316 HHACT_EXPAND = 5;
8317 HHACT_CONTRACT = 6;
8318 HHACT_BACK = 7;
8319 HHACT_FORWARD = 8;
8320 HHACT_STOP = 9;
8321 HHACT_REFRESH = 10;
8322 HHACT_HOME = 11;
8323 HHACT_SYNC = 12;
8324 HHACT_OPTIONS = 13;
8325 HHACT_PRINT = 14;
8326 HHACT_HIGHLIGHT = 15;
8327 HHACT_CUSTOMIZE = 16;
8328 HHACT_JUMP1 = 17;
8329 HHACT_JUMP2 = 18;
8330 HHACT_ZOOM = 19;
8331 HHACT_TOC_NEXT = 20;
8332 HHACT_TOC_PREV = 21;
8333 HHACT_NOTES = 22;
8335 HHACT_LAST_ENUM = 23;
8338 type
8339 {*** Notify event info for HHN_TRACK }
8340 PHHNTrack = ^THHNTrack;
8341 tagHHNTRACK = packed record //tagHHNTRACK, HHNTRACK;
8342 hdr: TNMHdr;
8343 pszCurUrl: PChar; // Multi-byte, null-terminated string
8344 idAction: Integer; // HHACT_ value
8345 phhWinType: PHHWinType; // Current window type structure
8346 end;
8347 HHNTRACK = tagHHNTRACK;
8348 THHNTrack = tagHHNTRACK;
8351 ///////////////////////////////////////////////////////////////////////////////
8353 // Global Control Properties.
8355 const
8356 HH_GPROPID_SINGLETHREAD = 1; // VARIANT_BOOL: True for single thread
8357 HH_GPROPID_TOOLBAR_MARGIN = 2; // long: Provides a left/right margin around the toolbar.
8358 HH_GPROPID_UI_LANGUAGE = 3; // long: LangId of the UI.
8359 HH_GPROPID_CURRENT_SUBSET = 4; // BSTR: Current subset.
8360 HH_GPROPID_CONTENT_LANGUAGE = 5; // long: LandId for desired content.
8362 type
8363 tagHH_GPROPID = HH_GPROPID_SINGLETHREAD..HH_GPROPID_CONTENT_LANGUAGE; //tagHH_GPROPID, HH_GPROPID
8364 HH_GPROPID = tagHH_GPROPID;
8365 THHGPropID = HH_GPROPID;
8367 ///////////////////////////////////////////////////////////////////////////////
8369 // Global Property structure
8371 {type
8372 PHHGlobalProperty = ^THHGlobalProperty;
8373 tagHH_GLOBAL_PROPERTY = record //tagHH_GLOBAL_PROPERTY, HH_GLOBAL_PROPERTY
8374 id: THHGPropID;
8375 Dummy: Integer; // Added to enforce 8-byte packing
8376 var_: VARIANT;
8377 end;
8378 HH_GLOBAL_PROPERTY = tagHH_GLOBAL_PROPERTY;
8379 THHGlobalProperty = tagHH_GLOBAL_PROPERTY;}
8380 //[END OF HTMLHELP DECLARATIONS]
8382 //[GetCtlBrush DECLARATIONS]
8383 function SimpleGetCtlBrushHandle( Sender: PControl ): HBrush; //forward;
8386 Global_GetCtlBrushHandle: function( Sender: PControl ): HBrush = SimpleGetCtlBrushHandle;
8387 {* Is called to obtain brush handle. }
8389 Global_Align: procedure( Sender: PObj ) = DummyObjProc;
8390 {* Is set to perform aligning of control, and only if property Align
8391 is changed for TControl, or SetAlign method is called for it. }
8393 //[WndFunc DECLARATION]
8394 function WndFunc( W: HWnd; Msg: Cardinal; wParam, lParam: Integer )
8395 : Integer; stdcall;
8396 {* Global message handler for window. Redirects all messages to
8397 destination windows, obtaining target TControl object address from
8398 window itself, using GetProp API call. }
8400 //[Applet VARIABLES]
8401 var AppletRunning: Boolean;
8402 {* Is set to True while message loop is processing (in Run procedure). }
8403 AppletTerminated: Boolean;
8404 {* Is set to True when message loop is terminated. }
8405 Applet: PControl;
8406 {* Applet window object. Actually, can be set to main form if program
8407 not needed in special applet button window (useful to make applet
8408 button invisible on taskbar, or to have several forms with single
8409 applet button - crete it in that case using NewApplet). }
8410 AppButtonUsed: Boolean;
8411 {* True if special window to represent applet button (may be invisible)
8412 is used. If no, every form is represented with its own taskbar button
8413 (always visible). }
8415 //[Screen DECLARATIONS]
8416 ScreenCursor: HCursor;
8417 {* Set this global variable to override any cursor settings of current
8418 form or control. }
8420 function ScreenWidth: Integer;
8421 {* Returns screen width in pixels. }
8422 function ScreenHeight: Integer;
8423 {* Returns screen height in pixels. }
8425 //[Status DECLARATIONS]
8426 type
8427 TStatusOption = ( soNoSizeGrip, soTop );
8428 {* Options available for status bars. }
8429 TStatusOptions = Set of TStatusOption;
8430 {* Status bar options. }
8436 //[Run DECLARATION]
8437 procedure Run( var AppletWnd: PControl );
8438 {* |<#appbutton>
8439 Call this procedure to process messages loop of your program.
8440 Pass here pointer to applet button object (if You have created it
8441 - see NewApplet) or your main form object of type PControl (created
8442 using NewForm).
8443 |<br><br>
8444 |<h1 align=center><font color=#FF8040><a name="visual_objects_constructors"></a>
8445 Visual objects constructing functions
8446 |</font></h1>
8447 Following constructing functions for visual controls are available:
8448 |#control
8451 //[Applet FUNCTIONS DECLARATIONS]
8452 procedure AppletMinimize;
8453 {* Minimizes the application (Applet should be assigned to have effect). }
8454 procedure AppletHide;
8455 {* Minimizes and hides application. }
8456 procedure AppletRestore;
8457 {* Restores Applet when minimized. }
8459 //[Idle handler DECALRATIONS]
8460 {YS+}
8461 procedure RegisterIdleHandler( const OnIdle: TOnEvent );
8462 {* Registers new Idle handler. Idle handler is called each time when
8463 message queue becomes empty. }
8464 procedure UnRegisterIdleHandler( const OnIdle: TOnEvent );
8465 {* Unregisters Idle handler. }
8466 {YS-}
8470 //[InitCommonXXXX ANOTHER DECLARATIONS]
8472 {* ComCtrl32 controls initialization. }
8473 procedure InitCommonControls; stdcall;
8474 procedure DoInitCommonControls( dwICC: DWORD );
8475 {* Calls extended initialization for Common Controls (from ComCtrl32).
8476 Pass one of following constants:
8477 |<pre>
8478 ICC_LISTVIEW_CLASSES = $00000001; // listview, header
8479 ICC_TREEVIEW_CLASSES = $00000002; // treeview, tooltips
8480 ICC_BAR_CLASSES = $00000004; // toolbar, statusbar, trackbar, tooltips
8481 ICC_TAB_CLASSES = $00000008; // tab, tooltips
8482 ICC_UPDOWN_CLASS = $00000010; // updown
8483 ICC_PROGRESS_CLASS = $00000020; // progress
8484 ICC_HOTKEY_CLASS = $00000040; // hotkey
8485 ICC_ANIMATE_CLASS = $00000080; // animate
8486 ICC_WIN95_CLASSES = $000000FF;
8487 ICC_DATE_CLASSES = $00000100; // month picker, date picker, time picker, updown
8488 ICC_USEREX_CLASSES = $00000200; // comboex
8489 ICC_COOL_CLASSES = $00000400; // rebar (coolbar) control
8490 ICC_INTERNET_CLASSES = $00000800;
8491 ICC_PAGESCROLLER_CLASS = $00001000; // page scroller
8492 ICC_NATIVEFNTCTL_CLASS = $00002000; // native font control
8493 |</pre>
8496 const
8497 ICC_LISTVIEW_CLASSES = $00000001; // listview, header
8498 ICC_TREEVIEW_CLASSES = $00000002; // treeview, tooltips
8499 ICC_BAR_CLASSES = $00000004; // toolbar, statusbar, trackbar, tooltips
8500 ICC_TAB_CLASSES = $00000008; // tab, tooltips
8501 ICC_UPDOWN_CLASS = $00000010; // updown
8502 ICC_PROGRESS_CLASS = $00000020; // progress
8503 ICC_HOTKEY_CLASS = $00000040; // hotkey
8504 ICC_ANIMATE_CLASS = $00000080; // animate
8505 ICC_WIN95_CLASSES = $000000FF;
8506 ICC_DATE_CLASSES = $00000100; // month picker, date picker, time picker, updown
8507 ICC_USEREX_CLASSES = $00000200; // comboex
8508 ICC_COOL_CLASSES = $00000400; // rebar (coolbar) control
8509 ICC_INTERNET_CLASSES = $00000800;
8510 ICC_PAGESCROLLER_CLASS = $00001000; // page scroller
8511 ICC_NATIVEFNTCTL_CLASS = $00002000; // native font control
8513 //[Ole DECLARATIONS]
8514 function OleInit: Boolean;
8515 {* Calls OleInitialize (once - all other calls are simulated by incrementing
8516 call counter. Every OleInit shoud be complemented with correspondent OleUninit.
8517 (Though, it is possible to call API function OleUnInitialize once to
8518 cancel all OleInit calls). }
8519 procedure OleUnInit;
8520 {* Decrements counter and calls OleUnInitialize when it is zeroed. }
8521 var OleInitCount: Integer;
8524 function StringToOleStr(const Source: string): PWideChar;
8525 {* }
8528 function SysAllocStringLen(psz: PWideChar; len: Integer): PWideChar; stdcall;
8529 procedure SysFreeString( psz: PWideChar ); stdcall;
8540 { -- Contructors for visual controls -- }
8541 //[NewXXXX DECLARATIONS]
8543 //[_NewWindowed DECLARATION]
8544 function _NewWindowed( AParent: PControl; ControlClassName: PChar; Ctl3D: Boolean ): PControl;
8546 //[NewApplet DECLARATION]
8547 function NewApplet( const Caption: String ): PControl;
8548 {* |<#control>
8549 Creates applet button window, which has to be parent of all other forms
8550 in your project (but this is *not must*). See also comments about NewForm.
8551 |<br>
8552 Following methods, properties and events are useful to work with applet
8553 control:
8554 |#appbutton }
8556 //[NewForm DECLARATION]
8557 function NewForm( AParent: PControl; const Caption: String ): PControl;
8558 {* |<#control>
8559 Creates form window object and returns pointer to it. If You use only one form,
8560 and You are not going to do applet button on task bar invisible, it is not
8561 necessary to create also special applet button window - just pass
8562 your (main) form object to Run procedure. In that case, it is a good
8563 idea to assign pointer to your main form object to Applet variable
8564 immediately following creating it - because some objects (e.g. TTimer)
8565 want to have Applet assigned to something.
8566 |<br>
8567 |&D=<a href="tcontrol.htm#%1" target=_top> %0 </a>
8568 Following methods, properties and events are useful to work with forms
8569 (ones common for all visual objects, such as <D Left>, <D Top>, <D Width>,
8570 <D Height>, etc. are not listed here - look TControl for it):
8571 |#form }
8573 //[_NewControl DECLARATION]
8574 function _NewControl( AParent: PControl; ControlClassName: PChar;
8575 Style: DWORD; Ctl3D: Boolean; Actions: PCommandActions ): PControl;
8577 //[NewButton DECLARATION]
8578 function NewButton( AParent: PControl; const Caption: String ): PControl;
8579 {* |<#control>
8580 Creates button on given parent control or form.
8581 Please note, that in Windows, buttons can not change its <D Font> color
8582 and to be <D Transparent>.
8583 |<br> Following methods, properies and events are (especially) useful with
8584 a button:
8585 |#button }
8587 //[NewBitBtn DECLARATION]
8588 function NewBitBtn( AParent: PControl; const Caption: String;
8589 Options: TBitBtnOptions; Layout: TGlyphLayout; GlyphBitmap: HBitmap; GlyphCount: Integer ): PControl;
8590 {* |<#control>
8591 Creates image button (actually implemented as owner-drawn). In Options,
8592 it is possible to determine, whether bitmap or image list used to contain
8593 one or more (up to 5) images, correspondent to certain BitBtn state.
8594 |<br>&nbsp;&nbsp;&nbsp;
8595 For case of imagelist (option bboImageList), it is possible to use a
8596 number of glyphs from the image list, starting from image index given
8597 by GlyphCount parameter. Number of used glyphs is passed in that case
8598 in high word of GlyphCount parameter (if 0, one image is used therefore).
8599 For bboImageList, BitBtn can be Transparent (and in that case bboNoBorder
8600 style can be useful to draw custom buttons of non-rectangular shape).
8601 |<br>&nbsp;&nbsp;&nbsp;
8602 For case of bitmap BitBtn, image is stretched down (if too big), but can
8603 not be transparent. It is not necessary for bitmap BitBtn to pass correct
8604 GlyphCount - it is calculated on base of bitmap size, if 0 is passed.
8605 |<br>&nbsp;&nbsp;&nbsp;
8606 And, certainly, BitBtn can be without glyph image (text only). For that
8607 case, it is therefore is more flexible and power than usual Button (but
8608 requires more code). E.g., BitBtn can change its <D Font>, <D Color>,
8609 and to be totally <D Transparent>.
8610 Moreover, BitBtn can be <D Flat>, bboFixed, <D SpeedButton> and
8611 have property <D RepeatInterval>.
8612 |<br>&nbsp;&nbsp;&nbsp;
8613 Note: if You use bboFixed Style, use OnChange event instead of OnClick,
8614 because <D Checked> state is changed immediately however OnClick occure
8615 only when mouse or space key released (and can be not called at all if
8616 mouse button is released out of BitBtn bounds). Also, bboFixed defines
8617 only which glyph to show (the border if it is not turned off behaves as
8618 usual for a button, i.e. it becomes lowered and then raised again at any click).
8619 Here You can find references to other properties, events and methods
8620 applicable to BitBtn:
8621 |#bitbtn }
8623 //[NewLabel DECLARATION]
8624 function NewLabel( AParent: PControl; const Caption: String ): PControl;
8625 {* |<#control>
8626 Creates static text control (native Windows STATIC control).
8627 Use property <D Caption> at run time to change label text. Also
8628 it is possible to adjust label <D Font>, <D Brush> or <D Color>.
8629 Label can be <D Transparent>. If You want to have rotated text
8630 label, call NewLabelEffect instead and change its <D Font>.FontOrientation.
8631 Other references certain for a label:
8632 |#label }
8634 //[NewWordWrapLabel DECLARATION]
8635 function NewWordWrapLabel( AParent: PControl; const Caption: String ): PControl;
8636 {* |<#control>
8637 Creates multiline static text control (native Windows STATIC control),
8638 which can wrap long text onto several lines. See also NewLabel.
8639 See also:
8640 |#wwlabel
8641 |#label }
8643 //[NewLabelEffect DECLARATION]
8644 function NewLabelEffect( AParent: PControl; const Caption: String; ShadowDeep: Integer ): PControl;
8645 {* |<#control>
8646 Creates 3D-label with capability to rotate its text <D Caption>, which
8647 is controlled by changing <D Font>.FontOrientation property. If You want
8648 to get flat effect label (e.g. to rotate it only), pass <D ShadowDeep> = 0.
8649 Please note, that drawing procedure uses <D Canvas> property, so using of
8650 LabelEffect leads to increase size of executable.
8651 See also:
8652 |#3dlabel
8653 |#label }
8655 //[NewPaintbox DECLARATION]
8656 function NewPaintbox( AParent: PControl ): PControl;
8657 {* |<#control>
8658 Creates owner-drawn STATIC control. Set its <D OnPaint> event to
8659 perform custom painting.
8660 |#paintbox }
8662 //[NewImageShow DECLARATION]
8663 function NewImageShow( AParent: PControl; AImgList: PImageList; ImgIdx: Integer ): PControl;
8664 {* |<#control>
8665 Creates an image show control, implemented as a paintbox which is used to
8666 draw an image from the imagelist. At run-time, use property CurIndex to
8667 select another image from the imagelist, and a property ImageListNormal to
8668 use another image list. When the control is created, its size becomes
8669 equal to dimensions of imagelist (if any). }
8671 //[NewScrollBar DECLARATION]
8672 function NewScrollBar( AParent: PControl; BarSide: TScrollerBar ): PControl;
8673 { * not yet finished... }
8675 //[NewScrollBox DECLARATION]
8676 function NewScrollBox( AParent: PControl; EdgeStyle: TEdgeStyle;
8677 Bars: TScrollerBars ): PControl;
8678 {* |<#control>
8679 Creates simple scrolling box, which can be used any way you wish, e.g. to scroll
8680 certain large image. To provide automatic scrolling of a set of child controls,
8681 use advanced scroll box, created with NewScrollBoxEx. }
8683 procedure NotifyScrollBox( Self_, Child: PControl );
8686 function NewScrollBoxEx( AParent: PControl; EdgeStyle: TEdgeStyle ): PControl;
8687 {* |<#control>
8688 Creates extended scrolling box control, which automatically scrolls child
8689 controls (if any). }
8691 //[NewGradientPanel DECLARATION]
8692 function NewGradientPanel( AParent: PControl; Color1, Color2: TColor ): PControl;
8693 {* |<#control>
8694 Creates gradient-filled STATIC control. To adjust colors at the
8695 run time, change <D Color1> and <D Color2> properties (which initially are
8696 assigned from Color1, Color2 parameters), and call <D Invalidate> method
8697 to repaint control. }
8699 function NewGradientPanelEx( AParent: PControl; Color1, Color2: TColor;
8700 Style: TGradientStyle; Layout: TGradientLayout ): PControl;
8701 {* |<#control>
8702 Creates gradient-filled STATIC control. To adjust colors at the
8703 run time, change <D Color1> and <D Color2> properties (which initially are
8704 assigned from Color1, Color2 parameters), and call <D Invalidate> method
8705 to repaint control. Depending on style and first line/point layout, can
8706 looking different. Idea: Vladimir Stojiljkovic. }
8708 //[NewPanel DECLARATION]
8709 function NewPanel( AParent: PControl; EdgeStyle: TEdgeStyle ): PControl;
8710 {* |<#control>
8711 Creates panel, which can be parent for other controls (though, any
8712 control can be used as a parent for other ones, but panel is specially
8713 designed for such purpose). }
8715 //[NewMDIxxx DECLARATIONS]
8716 function NewMDIClient( AParent: PControl; WindowMenu: THandle ): PControl;
8717 {* |<#control>
8718 Creates MDI client window, which is a special type of child window,
8719 containing all MDI child windows, created calling NewMDIChild function.
8720 On a form, MDI client behaves like a panel, so it can be placed and sized
8721 (or aligned) like any other controls. To minimize flick during resizing
8722 main form having another aligned controls, place MDI client window on
8723 a panel and align it caClient in the panel.
8724 |<br>Note:
8725 MDI client must be a single on the form. }
8727 function NewMDIChild( AParent: PControl; const ACaption: String ): PControl;
8728 {* |<#control>
8729 Creates MDI client window. AParent should be a MDI client window,
8730 created with NewMDIClient function. }
8732 //[NewSplitter DECLARATIONS]
8733 function NewSplitter( AParent: PControl; MinSizePrev, MinSizeNext: Integer ): PControl;
8734 {* |<#control>
8735 Creates splitter control, which will separate previous one (i.e. last
8736 created one before splitter on the same parent) from created
8737 next, allowing to user to adjust size of separated controls by dragging
8738 the splitter in desired direction. Created splitter becomes vertical
8739 or horizontal depending on Align style of previous control on the same
8740 parent (if caLeft/caRight then vertical, if caTop/caBottom then horizontal).
8741 |<br>&nbsp;&nbsp;&nbsp;
8742 Please note, what if previous control has no Align equal to caLeft/caRight
8743 or caTop/caBottom, splitter will not be able to function normally. If
8744 previous control does not exist, it is yet possible to use splitter as
8745 a resizeable panel (but set its initial Align value first - otherwise it
8746 is not set by default. Also, change Cursor property as You wish in that
8747 case, since it is not set too in case, when previous control does not
8748 exist).
8749 |<br>&nbsp;&nbsp;&nbsp;
8750 Additional parameters determine, which minimal size (width or height -
8751 correspondently to split direction) is allowed for left (top) control
8752 and to rest of client area of parent, correspondently. (It is possible
8753 later to set second control for checking its size with MinSizeNext
8754 value - using TControl.SecondControl property). If -1 passed,
8755 correspondent control size is not checked during dragging of splitter.
8756 Usually 0 is more suitable value (with this value, it is garantee, that
8757 splitter will be always available even if mouse was released far from the
8758 edge of form).
8759 |<br>&nbsp;&nbsp;&nbsp;
8760 It is possible for user to press Escape any time while dragging splitter
8761 to abort all adjustments made starting from left mouse button push and
8762 begin of drag the splitter. But remember please, that such event is
8763 controlled using timer, and therefore correspondent keyboard events
8764 are received by currently focused control. Be sure, that pressing Escape
8765 will not affect to any control on form, which could be focused, otherwise
8766 filter keyboard messages (by yourself) to prevent undesired handling of
8767 Escape key by certain controls while splitting. (Use Dragging property
8768 to check if splitter is dragging by user with mouse).
8769 |<br>&nbsp;&nbsp;&nbsp;
8770 See also:
8771 NewSplitterEx
8772 |#splitter }
8774 function NewSplitterEx( AParent: PControl; MinSizePrev, MinSizeNext: Integer;
8775 EdgeStyle: TEdgeStyle ): PControl;
8776 {* |<#control>
8777 Creates splitter control. Difference from NewSplitter is what it is possible
8778 to determine if a splitter will be beveled or not. See also NewSplitter. }
8780 //[NewGroupbox DECLARATION]
8781 function NewGroupbox( AParent: PControl; const Caption: String ): PControl;
8782 {* |<#control>
8783 Creates group box control. Note, that to group radio items, group
8784 box is not necessary - any parent can play role of group for radio items.
8785 See also NewPanel. }
8787 //[NewCheckbox DECLARATION]
8788 function NewCheckbox( AParent: PControl; const Caption: String ): PControl;
8789 {* |<#control>
8790 Creates check box control. Special properties, methods, events:
8791 |#checkbox }
8793 function NewCheckBox3State( AParent: PControl; const Caption: String ): PControl;
8794 {* |<#control>
8795 Creates check box control with 3 states. Special properties, methods,
8796 events:
8797 |#checkbox }
8799 //[NewRadiobox DECLARATION]
8800 function NewRadiobox( AParent: PControl; const Caption: String ): PControl;
8801 {* |<#control>
8802 Creates radio box control. Alternative radio items must have the
8803 same parent window (regardless of its kind, either groupbox (NewGroupbox),
8804 panel (NewPanel) or form itself). Following properties, methods and events
8805 are specially for radiobox controls:
8806 |#radiobox }
8808 //[NewEditbox DECLARATION]
8809 function NewEditbox( AParent: PControl; Options: TEditOptions ): PControl;
8810 {* |<#control>
8811 Creates edit box control. To create multiline edit box, similar to
8812 TMemo in VCL, apply eoMultiline in Options. Following properties, methods,
8813 events are special for edit controls:
8814 |#edit }
8816 //[NewRichEdit DECLARATION]
8817 function NewRichEdit( AParent: PControl; Options: TEditOptions ): PControl;
8818 {* |<#control>
8819 Creates rich text edit control. A rich edit control is a window in which
8820 the user can enter and edit text. The text can be assigned character and
8821 paragraph formatting, and can include embedded OLE objects. Rich edit
8822 controls provide a programming interface for formatting text. However, an
8823 application must implement any user interface components necessary to make
8824 formatting operations available to the user.
8825 |<br>&nbsp;&nbsp;&nbsp;
8826 Note: eoPassword, eoMultiline options have no effect for RichEdit control.
8827 Some operations are supersided with special versions of those, created
8828 especially for RichEdit, but in some cases it is necessary to use
8829 another properties and methods, specially designed for RichEdit (see
8830 methods and properties, which names are starting from RE_...).
8831 |<br>&nbsp;&nbsp;&nbsp;
8832 Following properties, methods, events are special for edit controls:
8833 |#richedit
8836 function NewRichEdit1( AParent: PControl; Options: TEditOptions ): PControl;
8837 {* |<#control>
8838 Like NewRichEdit, but to work with older RichEdit control version 1.0
8839 (window class 'RichEdit' forced to use instead of 'RichEdit20A', even
8840 if library RICHED20.DLL found and loaded successfully). One more
8841 difference - OleInit is not called, so the most of OLE capabilities
8842 of RichEdit could not working. }
8844 //[NewListbox DECLARATION]
8845 function NewListbox( AParent: PControl; Options: TListOptions ): PControl;
8846 {* |<#control>
8847 Creates list box control. Following properties, methods and events are
8848 special for Listbox:
8849 |#listbox }
8851 //[NewCombobox DECLARATION]
8852 function NewCombobox( AParent: PControl; Options: TComboOptions ): PControl;
8853 {* |<#control>
8854 Creates new combo box control. Note, that it is not possible to align
8855 combobox caLeft or caRight: this can cause infinit recursion in the
8856 application.
8857 |<br>Following properties, methods and events are
8858 special for Combobox:
8859 |#combo }
8861 //[_NewCommonControl DECLARATION]
8862 function _NewCommonControl( AParent: PControl; ClassName: PChar; Style: DWORD;
8863 Ctl3D: Boolean; Actions: PCommandActions ): PControl;
8865 //[NewProgressbar DECLARATION]
8866 function NewProgressbar( AParent: PControl ): PControl;
8867 {* |<#control>
8868 Creates progress bar control. Following properties are special for
8869 progress bar:
8870 |#progressbar
8871 See also NewProgressEx. }
8873 function NewProgressbarEx( AParent: PControl; Options: TProgressbarOptions ): PControl;
8874 {* |<#control>
8875 Can create progress bar with smooth style (progress is not segmented
8876 onto bricks) or/and vertical progress bar - using additional parameter.
8877 For list of properties, suitable for progress bars, see NewProgressbar. }
8879 //[NewListVew DECLARATION]
8880 function NewListView( AParent: PControl; Style: TListViewStyle; Options: TListViewOptions;
8881 ImageListSmall, ImageListNormal, ImageListState: PImageList ): PControl;
8882 {* |<#control>
8883 Creates list view control. It is very powerful control, which can partially
8884 compensate absence of grid controls (in lvsDetail view mode). Properties,
8885 methods and events, special for list view control are:
8886 |#listview }
8888 //[NewTreeView DECLARATION]
8889 function NewTreeView( AParent: PControl; Options: TTreeViewOptions;
8890 ImgListNormal, ImgListState: PImageList ): PControl;
8891 {* |<#control>
8892 Creates tree view control. See tree view methods and properties:
8893 |#treeview }
8895 //[NewTabControl DECLARATION]
8896 function NewTabControl( AParent: PControl; Tabs: array of String; Options: TTabControlOptions;
8897 ImgList: PImageList; ImgList1stIdx: Integer ): PControl;
8898 {* |<#control>
8899 Creates new tab control (like notebook). To place child control on a certain
8900 page of TabControl, use property Pages[ Idx ], for example:
8901 ! Label1 := NewLabel( TabControl1.Pages[ 0 ], 'Label1' );
8902 | &nbsp;&nbsp;&nbsp;
8903 To determine number of pages at run time, use property <D Count>;
8904 |<br> to determine which page is currently selected (or to change
8905 selection), use property <D CurrentIndex>;
8906 |<br> to feedback to switch between tabs assign your handler to OnSelChange
8907 event;
8908 |<br>Note, that by default, tab control is created with a border lowered to
8909 tab control's parent. To remove it, you can apply WS_EX_TRANSPARENT extended
8910 style (see TControl.ExStyle property), but painting of some child controls
8911 can be strange a bit in this case (no border drawing for edit controls was
8912 found, but not always...). You can also apply style WS_THICKFRAME (TControl.Style
8913 property) to make the border raised.
8914 |<br> Other methods and properties, suitable for tab control, are:
8915 |#tabcontrol }
8917 //[NewToolbar DECLARATION]
8918 function NewToolbar( AParent: PControl; Align: TControlAlign; Options: TToolbarOptions;
8919 Bitmap: HBitmap; Buttons: array of PChar;
8920 BtnImgIdxArray: array of Integer ) : PControl;
8921 {* |<#control>
8922 Creates toolbar control. Bitmap must contain images for all buttons
8923 excluding separators (defined by string '-' in Buttons array), otherwise
8924 last buttons will no have images at all. Image width for every button
8925 is assumed to be equal to Bitmap height (if last of "squares" has
8926 insufficient width, it will not be used). To define fixed buttons, use
8927 characters '+' or '-' as a prefix for button string (even empty). To
8928 create groups of (radio-)buttons, use also '!' follow '+' or '-'. (These rules
8929 are similar used in menu creation). To define drop down button, use (as
8930 first) prefix '^'. (Do not forget to set <D OnTBDropDown> event for this
8931 case). If You want to assign images to buttons not in the same order
8932 how these are placed in Bitmap (or You use system bitmap), define for every
8933 button (in BtnImgIdxArray array) indexes for every button (excluding
8934 separator buttons). Otherwise, it is possible to define index only for first
8935 button (e.g., [0]). It is also possible to change TBImages[ ] property
8936 for such purpose, or do the same in method TBSetBtnImgIdx).
8937 |<br>
8938 Following properties, methods and event are specially designed to work with
8939 toolbar control:
8940 |#toolbar
8941 |<br>&nbsp;&nbsp;&nbsp;
8942 If your project uses Align property to align controls, this can conflict with
8943 toolbar native aligning. To solve such problem, place toolbar to parent panel,
8944 which has its own Align property assigned to desired value.
8945 |<br>
8946 To create toolbar with buttons, drawn from top to bottom, instead from left
8947 to right, combine caLeft / caRight in Align parameter and style tboWrapable
8948 when create toolbar. To adjust width of vertically aligned toolbar, it is
8949 possible to call ResizeParentLeft for it. E.g.:
8951 ! P0 := NewPanel( W, esRaised ) .SetSize( 30, 0 ) .SetAlign( caLeft );
8952 ! // ^^^^^^^^^^^^^^^^^ //////
8953 !TB := NewToolbar( P0, caLeft, [ tboNoDivider, tboWrapable ], DWORD(-1),
8954 ! // ////// ///////////
8955 ! [ ' ', ' ', ' ', '-', ' ', ' ' ],
8956 ! [ STD_FILEOPEN ] ).ResizeParentRight;
8957 !//Note, that caLeft is *must*, and tboWrapable style too. SetSize for
8958 !//parent panel is not necessary, but only if ResizeParentRight is called
8959 !//than for Toolbar.
8960 |<br><br>
8961 One more note: if You create toolbar without text labels (passing ' ' for
8962 each button You add), include also option tboTextRight to fix incorrect
8963 sizing of buttons under Windows9x.
8966 //[NewDateTimePicker DECLARATION]
8967 function NewDateTimePicker( AParent: PControl; Options: TDateTimePickerOptions )
8968 : PControl;
8969 {* |<#control>
8970 Creates date and time picker common control.
8975 { -- Constructor for Image List objet -- }
8977 //[NewImageList DECLARATION]
8978 function NewImageList( AOwner: PControl ): PImageList;
8979 {* Constructor of TImageList object. Unlike other non-visual objects, image list
8980 can be parented by TControl object (but this does not *must*), and in that
8981 case it is destroyed automatically when its parent control is destroyed.
8982 Every control can have several TImageList objects, linked to a simple list.
8983 But if any TImageList object is destroyed, all following ones are destroyed
8984 too (at least, now I implemented it so). }
9017 //[TIMER]
9018 type
9019 {++}(*TTimer = class;*){--}
9020 PTimer = {-}^{+}TTimer;
9021 { ----------------------------------------------------------------------
9023 TTimer object
9025 ----------------------------------------------------------------------- }
9026 //[TTimer DEFINITION]
9027 TTimer = object( TObj )
9028 {* Easy timer incapsulation object. Uses applet window to
9029 receive timer events. So, either assign your main form
9030 to Applet variable or create applet button object (and
9031 assign it to Applet) before enabling timer. }
9032 protected
9033 fHandle : Integer;
9034 fEnabled: Boolean;
9035 fInterval: Integer;
9036 fOnTimer: TOnEvent;
9037 procedure SetEnabled(const Value: Boolean); virtual;
9038 procedure SetInterval(const Value: Integer);
9039 protected
9040 {++}(*public*){--}
9041 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
9042 {* Destructor. }
9043 public
9044 property Handle : Integer read fHandle;
9045 {* Windows timer object handle. }
9046 property Enabled : Boolean read fEnabled write SetEnabled;
9047 {* True, is timer is on. Initially, always False. Before assigning True,
9048 make sure, that Applet global variable is assigned to applet object
9049 (NewApplet) or to form (NewForm). }
9050 property Interval : Integer read fInterval write SetInterval;
9051 {* Interval in milliseconds (1000 is default and means 1 second). }
9052 property OnTimer : TOnEvent read fOnTimer write fOnTimer;
9053 {* Event, which is called when time interval is over. }
9054 end;
9055 //[END OF TTimer DEFINITION]
9057 //[NewTimer DECLARATION]
9058 function NewTimer( Interval: Integer ): PTimer;
9059 {* Constructs initially disabled timer with interval 1000 (1 second). }
9062 //[MULTIMEDIA TIMER]
9063 type
9064 {++}(*TMMTimer = class;*){--}
9065 PMMTimer = {-}^{+}TMMTimer;
9067 //[TMMTimer DEFINITION]
9068 TMMTimer = object( TTimer )
9069 {* Multimedia timer incapsulation object. Does not require Applet or special
9070 window to handle it. System creates a thread for each high resolution
9071 timer, so using many such objects can degrade total PC performance. }
9072 protected
9073 FResolution: Integer;
9074 FPeriodic: Boolean;
9075 procedure SetEnabled(const Value: Boolean); {-}virtual;{+}{++}(*override;*){--}
9076 public
9077 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
9078 {* }
9079 property Resolution: Integer read FResolution write FResolution;
9080 {* Minimum timer resolution. The less the more accuracy (0 is exactly
9081 Interval milliseconds between timer shots). It is recommended to set
9082 this property greater to prevent entire system from reducing overhead.
9083 If you change this value, reset and then set Enabled again to apply
9084 changes. }
9085 property Periodic: Boolean read FPeriodic write FPeriodic;
9086 {* TRUE, if timer is periodic (default). Otherwise, timer is one-shot
9087 (set it Enabled every time in such case for each shot). If you change
9088 this property, reset and set Enabled property again to get effect. }
9089 end;
9090 //[END OF TMMTimer DEFINITION]
9092 //[NewMMTimer DECLARATION]
9093 function NewMMTimer( Interval: Integer ): PMMTimer;
9094 {* Creates multimedia timer object. Initially, it has Resolution = 0,
9095 Periodic = TRUE and Enabled = FALSE. Do not forget also to assign your
9096 event handler to OnTimer to do something on timer shot. }
9110 //[DIRCHANGE]
9111 type
9112 {++}(*TDirChange = class;*){--}
9113 PDirChange = {-}^{+}TDirChange;
9114 {* }
9116 TOnDirChange = procedure (Sender: PDirChange; const Path: string) of object;
9117 {* Event type to define OnChange event for folder monitoring objects. }
9119 TFileChangeFilters = (fncFileName, fncDirName, fncAttributes, fncSize,
9120 fncLastWrite, fncLastAccess, fncCreation, fncSecurity);
9121 {* Possible change monitor filters. }
9122 TFileChangeFilter = set of TFileChangeFilters;
9123 {* Set of filters to pass to a constructor of TDirChange object. }
9125 { ----------------------------------------------------------------------
9127 TDirChange object
9129 ----------------------------------------------------------------------- }
9130 //[TDirChange DEFINITION]
9131 TDirChange = object(TObj)
9132 {* Object type to monitor changes in certain folder. }
9133 protected
9134 FOnChange: TOnDirChange;
9135 FHandle: THandle;
9136 FPath: string;
9137 FMonitor: PThread;
9138 function Execute( Sender: PThread ): Integer;
9139 procedure Changed;
9140 protected
9141 {++}(*public*){--}
9142 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
9144 public
9145 property Handle: THandle read FHandle;
9146 {* Handle of file change notification object. *}
9147 property Path: String read FPath; //write SetPath;
9148 {* Path to monitored folder (to a root, if tree of folders
9149 is under monitoring). }
9150 end;
9151 //[END OF TDirChange DEFINITION]
9153 //[NewDirChangeNotifier DECLARATION]
9154 function NewDirChangeNotifier( const Path: String; Filter: TFileChangeFilter;
9155 WatchSubtree: Boolean; ChangeProc: TOnDirChange ): PDirChange;
9156 {* Creates notification object TDirChangeNotifier. If something wrong (e.g.,
9157 passed directory does not exist), nil is returned as a result. When change
9158 is notified, ChangeProc is called always in main thread context.
9159 (Please note, that ChangeProc can not be nil).
9160 If empty filter is passed, default filter is used:
9161 [fncFileName..fncLastWrite]. }
9170 { -- TTrayIcon object -- }
9171 //[TRAYICON]
9173 type
9174 TOnTrayIconMouse = procedure( Sender: PObj; Message : Word ) of object;
9175 {* Event type to be called when Applet receives a message from an icon,
9176 added to the taskbar tray. }
9178 {++}(*TTrayIcon = class;*){--}
9179 PTrayIcon = {-}^{+}TTrayIcon;
9180 { ----------------------------------------------------------------------
9182 TTrayIcon - icon in tray area of taskbar
9184 ----------------------------------------------------------------------- }
9185 //[TTrayIcon DEFINITION]
9186 TTrayIcon = object(TObj)
9187 {* Object to place (and change) a single icon onto taskbar tray. }
9188 protected
9189 FIcon: HIcon;
9190 FActive: Boolean;
9191 FTooltip: String;
9192 FOnMouse: TOnTrayIconMouse;
9193 FControl: PControl;
9194 fAutoRecreate: Boolean;
9195 FNoAutoDeactivate: Boolean;
9196 FWnd: HWnd;
9197 procedure SetIcon(const Value: HIcon);
9198 procedure SetActive(const Value: Boolean);
9199 procedure SetTrayIcon( const Value : DWORD );
9200 procedure SetTooltip(const Value: String);
9201 procedure SetAutoRecreate(const Value: Boolean);
9202 protected
9203 {++}(*public*){--}
9204 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
9205 {* Destructor. Use Free method instead (as usual). }
9206 public
9207 property Icon : HIcon read FIcon write SetIcon;
9208 {* Icon to be shown on taskbar tray. If not set, value of Active
9209 property has no effect. It is also possible to assign a value
9210 to Icon property after assigning True to Active to install
9211 icon first time or to replace icon with another one (e.g. to
9212 get animation effect).
9213 |<br>&nbsp;&nbsp;&nbsp;
9214 Previously allocated icon (if any) is not deleted using
9215 DeleteObject. This is normal for icons, loaded from resource
9216 (e.g., by LoadIcon API call). But if icon was created (e.g.) by
9217 CreateIconIndirect, your code is responsible for destroying
9218 of it). }
9219 property Active : Boolean read FActive write SetActive;
9220 {* Set it to True to show assigned Icon on taskbar tray. Default
9221 is False. Has no effect if Icon property is not assigned.
9222 TrayIcon is deactivated automatically when Applet is finishing
9223 (but only if Applet window is used as a "parent" for tray
9224 icon object). }
9225 property Tooltip : String read FTooltip write SetTooltip;
9226 {* Tooltip string, showing automatically when mouse is moving
9227 over installed icon. Though "huge string" type is used, only
9228 first 63 characters are considered. Also note, that only in
9229 most recent versions of Windows multiline tooltips are supported. }
9230 property OnMouse : TOnTrayIconMouse read FOnMouse write FOnMouse;
9231 {* Is called then mouse message is taking place concerning installed
9232 icon. Only type of message can be obtained (e.g. WM_MOUSEMOVE,
9233 WM_LBUTTONDOWN etc.) }
9234 property AutoRecreate: Boolean read fAutoRecreate write SetAutoRecreate;
9235 {* If set to TRUE, auto-recreating of tray icon is proveded in case,
9236 when Explorer is restarted for some (unpredictable) reasons. Otherwise,
9237 your tray icon is disappeared forever, and if this is the single way
9238 to communicate with your application, the user nomore can achieve it. }
9239 property NoAutoDeactivate: Boolean read FNoAutoDeactivate write FNoAutoDeactivate;
9240 {* If set to true, tray icon is not removed from tray automatically on
9241 WM_CLOSE message receive by owner control. Set Active := FALSE in
9242 your code for such case before accepting closing the form. }
9243 property Wnd: HWnd read FWnd write FWnd;
9244 {* A window to use as a base window for tray icon messages. Overrides
9245 parent Control handle is assigned. Note, that if Wnd property used,
9246 message handling is not done automatically, and you should do this in
9247 your code, or at least for one tray icon object, call AttachProc2Wnd. }
9248 procedure AttachProc2Wnd;
9249 {* Call this method for a tray icon object in case if Wnd used rather then
9250 control. It is enough to call this method once for each Wnd used, even
9251 if several other tray icons are also based on the same Wnd. See also
9252 DetachProc2Wnd method. }
9253 procedure DetachProc2Wnd;
9254 {* Call this method to detach window procedure attached via AttachProc2Wnd.
9255 Do it once for a Wnd, used as a base to handle tray icon messages.
9256 Caution! If you do not call this method before destroying Wnd, the
9257 application will not functioning normally. }
9258 end;
9259 {* When You create invisible application, which should be represented by
9260 only the tray icon, prepare a handle for the window, resposible for
9261 messages handling. Remember, that window handle is created automatically
9262 only when a window is showing first time. If window's property Visible is
9263 set to False, You should to call CreateWindow manually.
9264 <br>
9265 There is a known bug exist with similar invisible tray-iconized applications.
9266 When a menu is activated in response to tray mouse event, if there was
9267 not active window, belonging to the application, the menu is not disappeared
9268 when mouse is clicked anywhere else. This bug is occure in Windows9x/ME.
9269 To avoid it, activate first your form window. This last window shoud have
9270 status visible (but, certainly, there are no needs to place it on visible
9271 part of screen - change its position, so it will not be visible for user,
9272 if You wish).
9273 <br>
9274 Also, to make your application "invisible" but until special event is occure,
9275 use Applet separate from the main form, and make for both Visible := False.
9276 This allows for You to make your form visible any time You wish, and without
9277 making application button visible if You do not wish.
9279 {= Êîãäà Âû äåëàåòå íåâèäèìîå ïðèëîæåíèå, êîòîðîå äîëæíî áûòü ïðåäñòàâëåíî
9280 òîëüêî èêîíêîé â òðåå, îáåñïå÷üòå íåíóëåâîé Handle äëÿ îêíà, îòâå÷àþùåãî
9281 çà îáðàáîòêó ñîîáùåíèé. Ïîìíèòå, ÷òî Handle îêíà ñîçäàåòñÿ àâòîìàòè÷åñêè
9282 òîëüêî â òîò ìîìåíò, êîãäà îíî äîëæíî ïîÿâèòüñÿ â ïåðâûé ðàç. Åñëè ñâîéñòâî
9283 îêíà Visible óñòàíîâëåíî â FALSE, íåîáõîäèìî âûçâàòü CreateWindow ñàìîñòîÿòåëüíî.
9284 <br>
9285 Ñóùåñòâóåò èçâåñòíûé BUG ñ ïîäîáíûìè íåâèäèìûìè ìèíèìèçèðîâàííûìè â òðåé
9286 ïðèëîæåíèÿìè. Êîãäà â îòâåò íà ñîáûòèå ìûøè àêòèâèçèðâàíî âûïàäàþùåå ìåíþ,
9287 îíî íå èñ÷åçàåò ïî ùåë÷êó ìûøè âíå ýòîãî ìåíþ. Ïðîèñõîäèò ýòî â Windows9x/ME.
9288 ÷òîáû ðåøèòü ýòó ïðîáëåìó, ñíà÷àëà àêòèâèçèðóéòå ñâîå îêíî (ôîðìó). Ýòî îêíî
9289 äîëæíî áûòü âèäèìûì (íî, êîíå÷íî, åãî ìîæíî ðàçìåñòèòü âíå ïðåäåëîâ âèäèìîé
9290 ÷àñòè ýêðàíà, òàê ÷òî ïîëüçîâàòåëþ åãî âèäíî íå áóäåò).
9291 <br>
9292 Òàê æå, ÷òîáû ñäåëàòü ïðèëîæåíèå íåâèäèìûì, ïî êðàéíåé ìåðå, ïîêà ýòî íå
9293 ïîòðåáóåòñÿ, èñïîëüçóéòå îòäåëüíûé ïðåäñòàâèòåëü êëàññà TControl - ãëîáàëüíóþ
9294 ïåðåìåííóþ Applet, è ïðèñâîéòå FALSE åå ñâîéñòâó Visible.
9296 //[END OF TTrayIcon DEFINITION]
9298 //[NewTrayIcon DECLARATION]
9299 function NewTrayIcon( Wnd: PControl; Icon: HIcon ): PTrayIcon;
9300 {* Constructor of TTrayIcon object. Pass main form or applet as Wnd
9301 parameter. }
9314 //[JUST ONE]
9315 { -- JustOne -- }
9317 type
9318 TOnAnotherInstance = procedure( const CmdLine: String ) of object;
9319 {* Event type to use in JustOneNotify function. }
9321 function JustOne( Wnd: PControl; const Identifier : String ) : Boolean;
9322 {* Returns True, if this is a first instance. For all other instances
9323 (application is already running), False is returned. }
9325 function JustOneNotify( Wnd: PControl; const Identifier : String;
9326 const aOnAnotherInstance: TOnAnotherInstance ) : Boolean;
9327 {* Returns True, if this is a first instance. For all other instances
9328 (application is already running), False is returned. If handler
9329 aOnAnotherInstance passed, it is called (in first instance) every time
9330 when another instance of an application is started, receiving command
9331 line used to run it. }
9349 { -- string (mainly) utility procedures and functions. -- }
9351 //[Message Box DECLARATIONS]
9352 function MsgBox( const S: String; Flags: DWORD ): DWORD;
9353 {* Displays message box with the same title as Applet.Caption. If applet
9354 is not running, and Applet global variable is not assigned, caption
9355 'Error' is displayed (but actually this is not an error - the system
9356 does so, if nil is passed as a title).
9357 |<br>&nbsp;&nbsp;&nbsp;
9358 Returns ID_... result (correspondently to flags passed (MB_OK, MBYESNO,
9359 etc. -> ID_OK, ID_YES, ID_NO, etc.) }
9360 procedure MsgOK( const S: String );
9361 {* Displays message box with the same title as Applet.Caption (or 'Error',
9362 if Applet is not running). }
9363 function ShowMsg( const S: String; Flags: DWORD ): DWORD;
9364 {* Displays message box like MsgBox, but uses Applet.Handle as a parent
9365 (so the message has no button on a task bar). }
9366 procedure ShowMessage( const S: String );
9367 {* Like ShowMsg, but has only styles MB_OK and MB_SETFOREGROUND. }
9368 procedure ShowMsgModal( const S: String );
9369 {* This message function can be used out of a message loop (e.g., after
9370 finishing the application). It is always modal.
9371 Actually, a form with word-wrap label (decorated as borderless edit
9372 box with btnFace color) and with OK button is created and shown modal.
9373 When a dialog is called from outside message loop, caption 'Information'
9374 is always displayed.
9375 Dialog form is automatically resized vertically to fit message text
9376 (but until screen height is achieved) and shown always centered on
9377 screen. The width is fixed (400 pixels).
9378 |<br>
9379 Do not use this function outside the message loop for case, when the
9380 Applet variable is not used in an application. }
9381 function ShowQuestion( const S: String; Answers: String ): Integer;
9382 {* Modal dialog like ShowMsgModal. It is based on KOL form, so it can
9383 be called also out of message loop, e.g. after finishing the
9384 application. Also, this function *must* be used in MDI applications
9385 in place of any dialog functions, based on MessageBox.
9386 |<br>
9387 The second parameter should be empty string or several possible
9388 answers separated by '/', e.g.: 'Yes/No/Cancel'. Result is
9389 a number answered, starting from 1. For example, if 'Cancel'
9390 was pressed, 3 will be returned.
9391 |<br>
9392 User can also press ESCAPE key, or close modal dialog. In such case
9393 -1 is returned. }
9394 function ShowQuestionEx( const S: String; Answers: String; CallBack: TOnEvent ): Integer;
9395 {* Like ShowQuestion, but with CallBack function, called just before showing
9396 the dialog. }
9397 procedure SpeakerBeep( Freq: Word; Duration: DWORD );
9398 {* On Windows NT, calls Windows.Beep. On Windows 9x, produces beep on speaker
9399 of desired frequency during given duration time (in milliseconds). }
9401 {++}(*
9402 function FormatMessage(dwFlags: DWORD; lpSource: Pointer; dwMessageId: DWORD; dwLanguageId: DWORD;
9403 lpBuffer: PChar; nSize: DWORD; Arguments: Pointer): DWORD; stdcall;
9404 *){--}
9405 function SysErrorMessage(ErrorCode: Integer): string;
9406 {* Creates and returns a string containing formatted system error message.
9407 It is possible then to display this message or write it to a log
9408 file, e.g.:
9409 ! ShowMsg( SysErrorMessage( GetLastError ) );
9413 |&R=<a name="%0"></a><font color=#FF8040><h1>%0</h1></font>
9414 <R 64-bit integer numbers>
9416 //[I64 TYPE]
9417 type
9418 I64 = record
9419 {* 64 bit integer record. Use it and correspondent functions below in KOL
9420 projects to avoid dependancy from Delphi version (earlier versions of
9421 Delphi had no Int64 type). }
9422 Lo, Hi: DWORD;
9423 end;
9424 PI64 = ^I64;
9425 {* }
9429 {$IFNDEF _D4orHigher}
9430 Int64 = I64;
9431 PInt64 = PI64;
9432 {$ENDIF}
9434 function MakeInt64( Lo, Hi: DWORD ): I64;
9435 {* }
9436 function Int2Int64( X: Integer ): I64;
9437 {* }
9438 procedure IncInt64( var I64: I64; Delta: Integer );
9439 {* I64 := I64 + Delta; }
9440 procedure DecInt64( var I64: I64; Delta: Integer );
9441 {* I64 := I64 - Delta; }
9442 function Add64( const X, Y: I64 ): I64;
9443 {* Result := X + Y; }
9444 function Sub64( const X, Y: I64 ): I64;
9445 {* Result := X - Y; }
9446 function Neg64( const X: I64 ): I64;
9447 {* Result := -X; }
9448 function Mul64i( const X: I64; Mul: Integer ): I64;
9449 {* Result := X * Mul; }
9450 function Div64i( const X: I64; D: Integer ): I64;
9451 {* Result := X div D; }
9452 function Mod64i( const X: I64; D: Integer ): Integer;
9453 {* Result := X mod D; }
9454 function Sgn64( const X: I64 ): Integer;
9455 {* Result := sign( X ); i.e.:
9456 |<br>
9457 if X < 0 then -1
9458 |<br>
9459 if X = 0 then 0
9460 |<br>
9461 if X > 0 then 1 }
9462 function Cmp64( const X, Y: I64 ): Integer;
9463 {* Result := sign( X - Y ); i.e.
9464 |<br>
9465 if X < Y then -1
9466 |<br>
9467 if X = Y then 0
9468 |<br>
9469 if X > Y then 1 }
9470 function Int64_2Str( X: I64 ): String;
9471 {* }
9472 function Str2Int64( const S: String ): I64;
9473 {* }
9474 function Int64_2Double( const X: I64 ): Double;
9475 {* }
9476 function Double2Int64( D: Double ): I64;
9481 <R Floating point numbers>
9484 const
9485 NAN = 0.0 / 0.0;
9487 {++}(*const NAN = 1e-100;*){--}
9490 function IsNan(const AValue: Double): Boolean;
9491 {* Checks is an argument passed is NAN. }
9493 function IntPower(Base: Extended; Exponent: Integer): Extended;
9494 {* Result := Base ^ Exponent; }
9496 //[String<->Double DECLARATIONS]
9497 function Str2Double( const S: String ): Double;
9498 {* }
9500 function Double2Str( D: Double ): String;
9501 {* }
9502 function Extended2Str( E: Extended ): String;
9503 {* }
9505 function Double2StrEx( D: Double ): String;
9506 {* experimental, do not use }
9508 function TruncD( D: Double ): Double;
9509 {* Result := trunc( D ) as Double;
9510 |<hr>
9526 <R Small bit arrays (max 32 bits in array)>
9527 See also TBits object.
9530 //[SMALL BIT ARRAYS DECLARATIONS]
9531 function GetBits( N: DWORD; first, last: Byte ): DWord;
9532 {* Retuns bits straing from <first> and to <last> inclusively. }
9533 function GetBitsL( N: DWORD; from, len: Byte ): DWord;
9534 {* Retuns len bits starting from index <from>.
9535 |<hr>
9547 <R Arithmetics, geometry and other utility functions>
9549 See also units KolMath.pas, CplxMath.pas and Err.pas.
9551 //[MulDiv DECLARATION]
9552 {$IFNDEF FPC}
9553 function MulDiv( A, B, C: Integer ): Integer;
9554 {* Returns A * B div C. Small and fast. }
9555 {$ENDIF}
9557 //[TMethod TYPE]
9558 type
9559 ///////////////////////////////////////////
9560 {$ifndef _D6orHigher} //
9561 ///////////////////////////////////////////
9562 TMethod = packed record
9563 {* Is defined here because using of VCL classes.pas unit is
9564 not recommended in XCL. This record type is used often
9565 to set/access event handlers, referring to a procedure
9566 of object (usually to set such event to an ordinal
9567 procedure setting Data field to nil. }
9568 Code: Pointer; // Pointer to method code.
9569 {* If used to fake assigning to event handler of type 'procedure
9570 of object' with ordinal procedure pointer, use symbol '@'
9571 before method:
9572 |<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font face="Courier"><b>
9573 | Method.Code := @MyProcedure;
9574 |</b></font> }
9575 Data: Pointer; // Pointer to object, owning the method.
9576 {* To fake event of type 'procedure of object' with setting it to
9577 ordinal procedure assign here NIL; }
9578 end;
9579 {* When assigning TMethod record to event handler, typecast it with
9580 desired event type, e.g.:
9581 |<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font face="Courier"><b>
9582 | SomeObject.OnSomeEvent := TOnSomeEvent( Method );
9583 |</b></font><br> }
9584 ///////////////////////////////////////////
9585 {$endif} //
9586 ///////////////////////////////////////////
9587 PMethod = ^TMethod;
9588 {* }
9590 function MakeMethod( Data, Code: Pointer ): TMethod;
9591 {* Help function to construct TMethod record. Can be useful to
9592 assign regular type procedure/function as event handler for
9593 event, defined as object method (do not forget, that in that
9594 case it must have first dummy parameter to replace @Self,
9595 passed in EAX to methods of object). }
9597 //[Rectangles&Points DECLARATIONS]
9598 function MakeRect( Left, Top, Right, Bottom: Integer ): TRect; stdcall;
9599 {* Use it instead of VCL Rect function }
9600 function RectsEqual( const R1, R2: TRect ): Boolean;
9601 {* Returns True if rectangles R1 and R2 have the same bounds }
9602 function RectsIntersected( const R1, R2: TRect ): Boolean;
9603 {* Returns TRUE if rectangles R1 and R2 have at least one common point.
9604 Note, that right and bottom bounds of rectangles are not their part,
9605 so, if such points are lying on that bounds, FALSE is returned. }
9606 function PointInRect( const P: TPoint; const R: TRect ): Boolean;
9607 {* Returns True if point P is located in rectangle R (including
9608 left and top bounds but without right and bottom bounds of the
9609 rectangle). }
9610 function MakePoint( X, Y: Integer ): TPoint;
9611 {* Use instead of VCL function Point }
9612 //[MakeFlags DECLARATION]
9613 function MakeFlags( FlgSet: PDWORD; FlgArray: array of Integer): Integer;
9614 {* }
9616 function MakeDateTimeRange( D1, D2: TDateTime ): TDateTimeRange;
9617 {* Returns TDateTimeRange from two TDateTime bounds. }
9619 //[Integer FUNCTIONS DECLARATIONS]
9620 procedure Swap( var X, Y: Integer );
9621 {* exchanging values }
9622 function Min( X, Y: Integer ): Integer;
9623 {* minimum of two integers }
9624 function Max( X, Y: Integer ): Integer;
9625 {* maximum of two integers }
9626 function Abs( X: Integer ): Integer;
9627 {* absolute value }
9628 function Sgn( X: Integer ): Integer;
9629 {* sign of X: if X < 0, -1 is returned, if > 0, then +1, otherwise 0. }
9630 function iSqrt( X: Integer ): Integer;
9631 {* square root
9632 |<hr>
9637 <R String to number and number to string conversions>
9639 //[Integer<->String DECLARATIONS]
9640 function Int2Hex( Value : DWord; Digits : Integer ) : String;
9641 {* Converts integer Value into string with hex number. Digits parameter
9642 determines minimal number of digits (will be completed by adding
9643 necessary number of leading zeroes). }
9644 function Int2Str( Value : Integer ) : String;
9645 {* Obvious. }
9646 function UInt2Str( Value: DWORD ): String;
9647 {* The same as Int2Str, but for unsigned integer value. }
9648 function Int2StrEx( Value, MinWidth: Integer ): String;
9649 {* Like Int2Str, but resulting string filled with leading spaces to provide
9650 at least MinWidth characters. }
9651 function Int2Rome( Value: Integer ): String;
9652 {* Represents number 1..8999 to Rome numer. }
9653 function Int2Ths( I : Integer ) : String;
9654 {* Converts integer into string, separating every three digits from each
9655 other by ',' character. (Convert to thousands). }
9656 function Int2Digs( Value, Digits : Integer ) : String;
9657 {* Converts integer to string, inserting necessary number of leading zeroes
9658 to provide desired length of string, given by Digits parameter. If
9659 resulting string is greater then Digits, string is not truncated anyway. }
9660 function Num2Bytes( Value : Double ) : String;
9661 {* Converts double float to string, considering it as a bytes count.
9662 If Value is sufficiently large, number is represented in kilobytes (with
9663 following letter K), or in megabytes (M), gigabytes (G) or terabytes (T).
9664 Resulting string number is truncated to two decimals (.XX) or to one (.X),
9665 if the second is 0. }
9666 function S2Int( S: PChar ): Integer;
9667 {* Converts null-terminated string to Integer. Scanning stopped when any
9668 non-digit character found. Even empty string or string not containing
9669 valid integer number silently converted to 0. }
9670 function Str2Int(const Value : String) : Integer;
9671 {* Converts string to integer. First character, which can not be
9672 recognized as a part of number, regards as a separator. Even
9673 empty string or string without number silently converted to 0. }
9674 function Hex2Int( const Value : String) : Integer;
9675 {* Converts hexadecimal number to integer. Scanning is stopped
9676 when first non-hexadicimal character is found. Leading dollar ('$')
9677 character is skept (if present). Minus ('-') is not concerning as
9678 a sign of number and also stops scanning.}
9679 function cHex2Int( const Value : String) : Integer;
9680 {* As Hex2Int, but also checks for leading '0x' and skips it. }
9681 function Octal2Int( const Value: String ) : Integer;
9682 {* Converts octal number to integer. Scanning is stopped on first
9683 non-octal digit (any char except 0..7). There are no checking if
9684 there octal numer in the parameter. If the first char is not octal
9685 digit, 0 is returned. }
9686 function Binary2Int( const Value: String ) : Integer;
9687 {* Converts binary number to integer. Like Octal2Int, but only digits
9688 0 and 1 are allowed. }
9689 {$IFNDEF _FPC}
9690 function Format( const fmt: string; params: array of const ): String;
9691 {* Uses API call to wvsprintf, so does not understand extra formats,
9692 such as floating point, date/time, currency conversions. See list of
9693 available formats in win32.hlp (topic wsprintf).
9694 |<hr>
9698 <R Working with null-terminated and ansi strings>
9700 {$ENDIF _FPC}
9701 //[String FUNCTIONS DECLARATIONS]
9702 function StrComp(const Str1, Str2: PChar): Integer;
9703 {* Compares two strings fast. -1: Str1<Str2; 0: Str1=Str2; +1: Str1>Str2 }
9704 function StrComp_NoCase(const Str1, Str2: PChar): Integer;
9705 {* Compares two strings fast without case sensitivity.
9706 Returns: -1 when Str1<Str2; 0 when Str1=Str2; +1 when Str1>Str2 }
9707 function StrLComp(const Str1, Str2: PChar; MaxLen: Cardinal): Integer;
9708 {* Compare two strings (fast). Terminating 0 is not considered, so if
9709 strings are equal, comparing is continued up to MaxLen bytes.
9710 Since this, pass minimum of lengths as MaxLen. }
9711 function StrLComp_NoCase(const Str1, Str2: PChar; MaxLen: Cardinal): Integer;
9712 {* Compare two strings fast without case sensitivity.
9713 Terminating 0 is not considered, so if strings are equal,
9714 comparing is continued up to MaxLen bytes.
9715 Since this, pass minimum of lengths as MaxLen. }
9716 function StrCopy( Dest, Source: PChar ): PChar;
9717 {* Copy source string to destination (fast). Pointer to Dest is returned. }
9718 function StrCat( Dest, Source: PChar ): PChar;
9719 {* Append source string to destination (fast). Pointer to Dest is returned. }
9720 function StrLen(const Str: PChar): Cardinal;
9721 {* StrLen returns the number of characters in Str, not counting the null
9722 terminator. }
9723 function StrScanLen(Str: PChar; Chr: Char; Len: Integer): PChar;
9724 {* Fast scans string Str of length Len searching character Chr.
9725 Pointer to a character next to found or to Str[Len] (if no one found)
9726 is returned. }
9727 function StrScan(Str: PChar; Chr: Char): PChar;
9728 {* Fast search of given character in a string. Pointer to found character
9729 (or nil) is returned. }
9730 function StrRScan(const Str: PChar; Chr: Char): PChar;
9731 {* StrRScan returns a pointer to the last occurrence of Chr in Str. If Chr
9732 does not occur in Str, StrRScan returns NIL. The null terminator is
9733 considered to be part of the string. }
9734 function StrIsStartingFrom( Str, Pattern: PChar ): Boolean;
9735 {* Returns True, if string Str is starting from Pattern, i.e. if
9736 Copy( Str, 1, StrLen( Pattern ) ) = Pattern. Str must not be nil! }
9737 function StrIsStartingFromNoCase( Str, Pattern: PChar ): Boolean;
9738 {* Like StrIsStartingFrom above, but without case sensitivity. }
9739 function TrimLeft(const S: string): string;
9740 {* Removes spaces, tabulations and control characters from the starting
9741 of string S. }
9742 function TrimRight(const S: string): string;
9743 {* Removes spaces, tabulates and other control characters from the
9744 end of string S. }
9745 function Trim( const S : string): string;
9746 {* Makes TrimLeft and TrimRight for given string. }
9747 function RemoveSpaces( const S: String ): String;
9748 {* Removes all characters less or equal to ' ' in S and returns it. }
9749 procedure Str2LowerCase( S: PChar );
9750 {* Converts null-terminated string to lowercase (inplace). }
9751 function LowerCase(const S: string): string;
9752 {* Obvious. }
9753 function UpperCase(const S: string): string;
9754 {* Obvious. }
9755 function AnsiUpperCase(const S: string): string;
9756 {* Obvious. }
9757 function AnsiLowerCase(const S: string): string;
9758 {* Obvious. }
9759 {$IFNDEF _D2}
9760 {$IFNDEF _FPC}
9761 function WAnsiUpperCase(const S: WideString): WideString;
9762 {* Obvious. }
9763 function WAnsiLowerCase(const S: WideString): WideString;
9764 {* Obvious. }
9765 {$ENDIF _FPC}
9766 {$ENDIF _D2}
9767 function AnsiCompareStr(const S1, S2: string): Integer;
9768 {* AnsiCompareStr compares S1 to S2, with case-sensitivity. The compare
9769 operation is controlled by the current Windows locale. The return value
9770 is the same as for CompareStr. }
9771 function _AnsiCompareStr(S1, S2: PChar): Integer;
9772 {* The same, but for PChar ANSI strings }
9773 function AnsiCompareStrNoCase(const S1, S2: string): Integer;
9774 {* AnsiCompareStr compares S1 to S2, with case-sensitivity. The compare
9775 operation is controlled by the current Windows locale. The return value
9776 is the same as for CompareStr. }
9777 function _AnsiCompareStrNoCase(S1, S2: PChar): Integer;
9778 {* The same, but for PChar ANSI strings }
9779 function AnsiCompareText( const S1, S2: String ): Integer;
9780 {* }
9782 {$IFNDEF _FPC}
9783 function LStrFromPWCharLen(Source: PWideChar; Length: Integer): String;
9784 {* from Delphi5 - because D2 does not contain it. }
9785 function LStrFromPWChar(Source: PWideChar): String;
9786 {* from Delphi5 - because D2 does not contain it. }
9787 {$ENDIF _FPC}
9789 function CopyEnd( const S : String; Idx : Integer ) : String;
9790 {* Returns copy of source string S starting from Idx up to the end of
9791 string S. Works correctly for case, when Idx > Length( S ) (returns
9792 empty string for such case). }
9793 function CopyTail( const S : String; Len : Integer ) : String;
9794 {* Returns last Len characters of the source string. If Len > Length( S ),
9795 entire string S is returned. }
9796 procedure DeleteTail( var S : String; Len : Integer );
9797 {* Deletes last Len characters from string. }
9798 function IndexOfChar( const S : String; Chr : Char ) : Integer;
9799 {* Returns index of given character (1..Length(S)), or
9800 -1 if a character not found. }
9801 function IndexOfCharsMin( const S, Chars : String ) : Integer;
9802 {* Returns index (in string S) of those character, what is taking place
9803 in Chars string and located nearest to start of S. If no such
9804 characters in string S found, -1 is returned. }
9805 {$IFNDEF _D2}
9806 {$IFNDEF _FPC}
9807 function IndexOfWideCharsMin( const S, Chars : WideString ) : Integer;
9808 {* Returns index (in wide string S) of those wide character, what
9809 is taking place in Chars wide string and located nearest to start of S.
9810 If no such characters in string S found, -1 is returned. }
9811 {$ENDIF _FPC}
9812 {$ENDIF _D2}
9814 function IndexOfStr( const S, Sub : String ) : Integer;
9815 {* Returns index of given substring in source string S. If found,
9816 1..Length(S)-Length(Sub), if not found, -1. }
9817 function Parse( var S : String; const Separators : String ) : String;
9818 {* Returns first characters of string S, separated from others by
9819 one of characters, taking place in Separators string, assigning
9820 a tail of string (after found separator) to source string. If
9821 no separator characters found, source string S is returned, and
9822 source string itself becomes empty. }
9823 {$IFNDEF _FPC}
9824 {$IFNDEF _D2}
9825 function WParse( var S : WideString; const Separators : WideString ) : WideString;
9826 {* Returns first wide characters of wide string S, separated from others
9827 by one of wide characters, taking place in Separators wide string,
9828 assigning a tail of wide string (following found separator) to the
9829 source one. If there are no separator characters found, source wide
9830 string S is returned, and source wide string itself becomes empty. }
9831 {$ENDIF _D2}
9832 {$ENDIF _FPC}
9833 function ParsePascalString( var S : String; const Separators : String ) : String;
9834 {* Returns first characters of string S, separated from others by
9835 one of characters, taking place in Separators string, assigning
9836 a tail of string (after the found separator) to source string. If
9837 there are no separator characters found, the source string S is returned,
9838 and the source string itself becomes empty. Additionally: if the first (after
9839 a blank space) is the quote "'" or '#', pascal string is assumung first
9840 and is converted to usual string (without quotas) before analizing
9841 of other separators. }
9842 function String2PascalStrExpr( const S : String ) : String;
9843 {* Converts string to Pascal-like string expression (concatenation of
9844 strings with quotas and characters with leading '#'). }
9845 function StrEq( const S1, S2 : String ) : Boolean;
9846 {* Returns True, if LowerCase(S1) = LowerCase(S2). I.e., if strings
9847 are equal to each other without caring of characters case sensitivity
9848 (ASCII only). }
9849 function AnsiEq( const S1, S2 : String ) : Boolean;
9850 {* Returns True, if AnsiLowerCase(S1) = AnsiLowerCase(S2). I.e., if ANSI
9851 stringsare equal to each other without caring of characters case
9852 sensitivity. }
9853 {$IFNDEF _D2}
9854 {$IFNDEF _FPC}
9855 function WAnsiEq( const S1, S2 : WideString ) : Boolean;
9856 {* Returns True, if AnsiLowerCase(S1) = AnsiLowerCase(S2). I.e., if ANSI
9857 stringsare equal to each other without caring of characters case
9858 sensitivity. }
9859 {$ENDIF _FPC}
9860 {$ENDIF _D2}
9862 function StrIn( const S : String; const A : array of String ) : Boolean;
9863 {* Returns True, if S is "equal" to one of strings, taking place
9864 in A array. To check equality, StrEq function is used, i.e.
9865 comaprison is taking place without case sensitivity. }
9866 {$IFNDEF _FPC}
9867 {$IFNDEF _D2}
9868 function WStrIn( const S : WideString; const A : array of WideString ) : Boolean;
9869 {* Returns True, if S is "equal" to one of strings, taking place
9870 in A array. To check equality, WAnsiEq function is used, i.e.
9871 comaprison is taking place without case sensitivity. }
9872 {$ENDIF _D2}
9873 {$ENDIF _FPC}
9874 function StrIs( const S : String; const A : array of String; var Idx: Integer ) : Boolean;
9875 {* Returns True, if S is "equal" to one of strings, taking place
9876 in A array, and in such Case Idx also is assigned to an index of A element
9877 equal to S. To check equality, StrEq function is used, i.e.
9878 comaprison is taking place without case sensitivity. }
9879 function IntIn( Value: Integer; const List: array of Integer ): Boolean;
9880 {* Returns TRUE, if Value is found in a List. }
9881 function _StrSatisfy( S, Mask : PChar ) : Boolean;
9882 {* }
9883 function _2StrSatisfy( S, Mask: PChar ): Boolean;
9884 {* }
9885 function StrSatisfy( const S, Mask : String ) : Boolean;
9886 {* Returns True, if S is satisfying to a given Mask (which can contain
9887 wildcard symbols '*' and '?' interpeted correspondently as 'any
9888 set of characters' and 'single any character'. If there are no
9889 such wildcard symbols in a Mask, result is True only if S is maching
9890 to Mask string.) }
9891 function StrReplace( var S: String; const From, ReplTo: String ): Boolean;
9892 {* Replaces first occurance of From to ReplTo in S, returns True,
9893 if pattern From was found and replaced. }
9894 {$IFNDEF _FPC}
9895 {$IFNDEF _D2}
9896 function WStrReplace( var S: WideString; const From, ReplTo: WideString ): Boolean;
9897 {* Replaces first occurance of From to ReplTo in S, returns True,
9898 if pattern From was found and replaced. See also function StrReplace.
9899 This function is not available in Delphi2 (this version of Delphi
9900 does not support WideString type). }
9901 {$ENDIF _D2}
9902 {$ENDIF _FPC}
9904 function StrRepeat( const S: String; Count: Integer ): String;
9905 {* Repeats given string Count times. E.g., StrRepeat( 'A', 5 ) gives 'AAAAA'. }
9906 {$IFNDEF _FPC}
9907 {$IFNDEF _D2}
9908 function WStrRepeat( const S: WideString; Count: Integer ): WideString;
9909 {* Repeats given wide string Count times. E.g., StrRepeat( 'A', 5 ) gives 'AAAAA'. }
9910 {$ENDIF _D2}
9911 {$ENDIF _FPC}
9913 procedure NormalizeUnixText( var S: String );
9914 {* In the string S, replaces all occurances of character #10 (without leading #13)
9915 to the character #13. }
9917 {$IFNDEF _FPC}
9918 function WStrLen( W: PWideChar ): Integer;
9919 {* Returns Length of null-terminated Unicode string. }
9920 procedure WStrCopy( Dest, Src: PWideChar );
9921 {* Copies null-terminated Unicode string (terminated null also copied). }
9922 function WStrCmp( W1, W2: PWideChar ): Integer;
9923 {* Compares two null-terminated Unicode strings. }
9924 {$ENDIF _FPC}
9926 function StrPCopy(Dest: PChar; const Source: string): PChar;
9927 {* Copyes Pascal-style string into null-terminaed one. }
9928 function StrLCopy(Dest: PChar; const Source: PChar; MaxLen: Cardinal): PChar;
9929 {* Copyes first MaxLen characters of Pascal-style string into
9930 null-terminated one. }
9932 function DelimiterLast( const Str, Delimiters: String ): Integer;
9933 {* Returns index of the last of delimiters given by same named parameter
9934 among characters of Str. If there are no delimiters found, length of
9935 Str is returned. This function is intended mainly to use in filename
9936 parsing functions. }
9937 function __DelimiterLast( Str, Delimiters: PChar ): PChar;
9938 {* Returns address of the last of delimiters given by Delimiters parameter
9939 among characters of Str. If there are no delimeters found, position of
9940 the null terminator in Str is returned. This function is intended
9941 mainly to use in filename parsing functions. }
9942 function SkipSpaces( P: PChar ): PChar;
9943 {* Skips all characters #1..' ' in a string.
9945 {$IFDEF F_P}
9946 function DummyStrFun( const S: String ): String;
9947 {$ENDIF}
9950 //[Memory FUNCTIONS DECLARATIONS]
9951 function CompareMem(P1, P2: Pointer; Length: Integer): Boolean;
9952 {* Fast compare of two memory blocks. }
9953 function AllocMem( Size : Integer ) : Pointer;
9954 {* Allocates global memory and unlocks it. }
9955 procedure DisposeMem( var Addr : Pointer );
9956 {* Locks global memory block given by pointer, and frees it.
9957 Does nothing, if the pointer is nil.
9958 |<hr>
9960 <R Text in clipboard operations>
9963 //[clipboard FUNCTIONS DECLARATIONS]
9964 function Clipboard2Text: String;
9965 {* If clipboard contains text, this function returns it for You. }
9966 {$IFNDEF _FPC}
9967 {$IFNDEF _D2}
9968 function Clipboard2WText: WideString;
9969 {* If clipboard contains text, this function returns it for You (as Unicode string). }
9970 {$ENDIF _D2}
9971 {$ENDIF _FPC}
9972 function Text2Clipboard( const S: String ): Boolean;
9973 {* Puts given string to a clipboard. }
9974 {$IFNDEF _FPC}
9975 {$IFNDEF _D2}
9976 function WText2Clipboard( const WS: WideString ): Boolean;
9977 {* Puts given Unicode string to a clipboard.
9978 |<hr>
9980 {$ENDIF _D2}
9981 {$ENDIF _FPC}
9985 //[Mnemonics FUNCTIONS DECLARATIONS]
9986 var SearchMnemonics: function ( const S: String ): String
9987 = {$IFDEF F_P} DummyStrFun {$ELSE} UpperCase {$ENDIF};
9988 MnemonicsLocale: Integer;
9990 procedure SupportAnsiMnemonics( LocaleID: Integer );
9991 {* Provides encoding to work with given locale. Call this global function to
9992 extend TControl.SupportMnemonics capability (also should be called for a form
9993 or for Applet variable).
9999 <R Date and time handling>
10001 //[TDateTime TYPE DEFINITION]
10002 type
10003 //TDateTime = Double; // well, it is already defined so in System.pas
10004 {* Basic date and time type. Integer part represents year and days (as is,
10005 i.e. 1-Jan-2000 is representing by value 730141, which is a number of
10006 days from 1-Jan-0001 to 1-Jan-2000 inclusively). Fractional part is
10007 representing hours, minutes, seconds and milliseconds of a day
10008 proportionally (like in VCL TDateTime type, e.g. 0.5 = 12:00, 0.25 = 6:00,
10009 etc.). }
10011 PDayTable = ^TDayTable;
10012 TDayTable = array[1..12] of Word;
10014 TDateFormat = ( dfShortDate, dfLongDate );
10015 {* Date formats available to use in formatting date/time to string. }
10016 TTimeFormatFlag = ( tffNoMinutes, tffNoSeconds, tffNoMarker, tffForce24 );
10017 {* Additional flags, used for formatting time. }
10018 TTimeFormatFlags = Set of TTimeFormatFlag;
10019 {* Set of flags, used for formatting time. }
10021 const
10022 MonthDays: array [Boolean] of TDayTable =
10023 ((31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31),
10024 (31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31));
10025 {* The MonthDays array can be used to quickly find the number of
10026 days in a month: MonthDays[IsLeapYear(Y), M]. }
10028 SecsPerDay = 24 * 60 * 60;
10029 {* Seconds per day. }
10030 MSecsPerDay = SecsPerDay * 1000;
10031 {* Milliseconds per day. }
10033 VCLDate0 = 693594;
10034 {* Value to convert VCL "date 0" to KOL "date 0" and back.
10035 This value corresponds to 30-Dec-1899, 0:00:00. So,
10036 to convert VCL date to KOL date, just subtract this
10037 value from VCL date. And to convert back from KOL date
10038 to VCL date, add this value to KOL date.}
10040 {++}(*
10041 procedure GetLocalTime(var lpSystemTime: TSystemTime); stdcall;
10042 procedure GetSystemTime(var lpSystemTime: TSystemTime); stdcall;
10043 *){--}
10045 //[Date&Time FUNCTIONS DECLARATIONS]
10046 function Now : TDateTime;
10047 {* Returns local date and time on running PC. }
10048 function Date: TDateTime;
10049 {* Returns todaylocal date. }
10050 procedure DecodeDateFully( DateTime: TDateTime; var Year, Month, Day, DayOfWeek: WORD );
10051 {* Decodes date. }
10052 procedure DecodeDate( DateTime: TDateTime; var Year, Month, Day: WORD );
10053 {* Decodes date. }
10054 function EncodeDate( Year, Month, Day: WORD; var DateTime: TDateTime ): Boolean;
10055 {* Encodes date. }
10056 function CompareSystemTime(const D1, D2 : TSystemTime) : Integer;
10057 {* Compares to TSystemTime records. Returns -1, 0, or 1 if, correspondantly,
10058 D1 < D2, D1 = D2 and D1 > D2. }
10059 procedure IncDays( var SystemTime : TSystemTime; DaysNum : Integer );
10060 {* Increases/decreases day in TSystemTime record onto given days count
10061 (can be negative). }
10062 procedure IncMonths( var SystemTime : TSystemTime; MonthsNum : Integer );
10063 {* Increases/decreases month number in TSystemTime record onto given
10064 months count (can be negative). Correct result is not garantee if
10065 day number is incorrect for newly obtained month. }
10066 function IsLeapYear(Year: Word): Boolean;
10067 {* Returns True, if given year is "leap" (i.e. has 29 days in the February). }
10068 function DayOfWeek(Date: TDateTime): Integer;
10069 {* Returns day of week (0..6) for given date. }
10070 function SystemTime2DateTime(const SystemTime : TSystemTime; var DateTime : TDateTime ) : Boolean;
10071 {* Converts TSystemTime record to XDateTime variable. }
10072 function DateTime2SystemTime(const DateTime : TDateTime; var SystemTime : TSystemTime ) : Boolean;
10073 {* Converts TDateTime variable to TSystemTime record. }
10074 function DateTime_System2Local( DTSys: TDateTime ): TDateTime;
10075 {* Converts DTSys representing system time (+0 Grinvich) to local time. }
10076 function DateTime_Local2System( DTLoc: TDateTime ): TDateTime;
10077 {* Converts DTLoc representing local time to system time (+0 Grinvich) }
10078 function CatholicEaster( nYear: Integer ): TDateTime;
10079 {* Returns date of catholic easter for given year. }
10081 procedure DivMod(Dividend: Integer; Divisor: Word; var Result, Remainder: Word);
10082 {* Dividing of integer onto divisor with obtaining both result of division
10083 and remainder. }
10085 function SystemDate2Str( const SystemTime : TSystemTime; const LocaleID : DWORD;
10086 const DfltDateFormat : TDateFormat; const DateFormat : PChar ) : String;
10087 {* Formats date, stored in TSystemTime record into string, using given locale
10088 and date/time formatting flags. }
10089 function SystemTime2Str( const SystemTime : TSystemTime; const LocaleID : DWORD;
10090 const Flags : TTimeFormatFlags; const TimeFormat : PChar ) : String;
10091 {* Formats time, stored in TSystemTime record into string, using given locale
10092 and date/time formatting flags. }
10094 function Date2StrFmt( const Fmt: String; D: TDateTime ): String;
10095 {* Represents date as a string correspondently to Fmt formatting string.
10096 See possible pictures in definition of the function Str2DateTimeFmt
10097 (the first part). If Fmt string is empty, default system date format
10098 for short date string used. }
10099 function Time2StrFmt( const Fmt: String; D: TDateTime ): String;
10100 {* Represents time as a string correspondently to Fmt formatting string.
10101 See possible pictures in definition of the function Str2DateTimeFmt
10102 (the second part). If Fmt string is empty, default system time format
10103 for short date string used. }
10104 function DateTime2StrShort( D: TDateTime ): String;
10105 {* Formats date and time to string in short date format using current user
10106 locale. }
10107 function Str2DateTimeFmt( const sFmtStr, sS: String ): TDateTime;
10108 {* Restores date or/and time from string correspondently to a format string.
10109 Date and time formatting string can contain following pictures (case
10110 sensitive):
10111 |<pre>
10112 DATE PICTURES
10113 d Day of the month as digits without leading zeros for single digit days.
10114 dd Day of the month as digits with leading zeros for single digit days
10115 ddd Day of the week as a 3-letter abbreviation as specified by a
10116 LOCALE_SABBREVDAYNAME value.
10117 dddd Day of the week as specified by a LOCALE_SDAYNAME value.
10118 M Month as digits without leading zeros for single digit months.
10119 MM Month as digits with leading zeros for single digit months
10120 MMM Month as a three letter abbreviation as specified by a LOCALE_SABBREVMONTHNAME value.
10121 MMMM Month as specified by a LOCALE_SMONTHNAME value.
10122 y Year represented only be the last digit.
10123 yy Year represented only be the last two digits.
10124 yyyy Year represented by the full 4 digits.
10125 gg Period/era string as specified by the CAL_SERASTRING value. The gg
10126 format picture in a date string is ignored if there is no associated era
10127 string. In Enlish locales, usual values are BC or AD.
10129 TIME PICTURES
10130 h Hours without leading zeros for single-digit hours (12-hour clock).
10131 hh Hours with leading zeros for single-digit hours (12-hour clock).
10132 H Hours without leading zeros for single-digit hours (24-hour clock).
10133 HH Hours with leading zeros for single-digit hours (24-hour clock).
10134 m Minutes without leading zeros for single-digit minutes.
10135 mm Minutes with leading zeros for single-digit minutes.
10136 s Seconds without leading zeros for single-digit seconds.
10137 ss Seconds with leading zeros for single-digit seconds.
10138 t One character–time marker string (usually P or A, in English locales).
10139 tt Multicharacter–time marker string (usually PM or AM, in English locales).
10140 |</pre>
10141 E.g., 'D, yyyy/MM/dd h:mm:ss'.
10142 See also Str2DateTimeShort function.
10144 function Str2DateTimeShort( const S: String ): TDateTime;
10145 {* Restores date and time from string correspondently to current user locale. }
10146 function Str2DateTimeShortEx( const S: String ): TDateTime;
10147 {* Like Str2DateTimeShort above, but uses locale defined date and time
10148 separators to avoid recognizing time as a date in some cases.
10149 |<hr>
10152 <R File and directory routines>
10155 //[OpenFile CONSTANTS]
10156 const
10157 ofOpenRead = $80000000;
10158 {* Use this flag (in combination with others) to open file for "read" only. }
10159 ofOpenWrite = $40000000;
10160 {* Use this flag (in combination with others) to open file for "write" only. }
10161 ofOpenReadWrite = $C0000000;
10162 {* Use this flag (in combination with others) to open file for "read" and "write". }
10163 ofShareExclusive = $00;
10164 {* Use this flag (in combination with others) to open file for exclusive use. }
10165 ofShareDenyWrite = $01;
10166 {* Use this flag (in combination with others) to open file in share mode, when
10167 only attempts to open it in other process for "write" will be impossible.
10168 I.e., other processes could open this file simultaneously for read only
10169 access. }
10170 ofShareDenyRead = $02;
10171 {* Use this flag (in combination with others) to open file in share mode, when
10172 only attempts to open it for "read" in other processes will be disabled.
10173 I.e., other processes could open it for "write" only access. }
10174 ofShareDenyNone = $03;
10175 {* Use this flag (in combination with others) to open file in full sharing mode.
10176 I.e. any process will be able open this file using the same share flag. }
10177 ofCreateNew = $100;
10178 {* Default creation disposition. Use this flag for creating new file (usually
10179 for write access. }
10180 ofCreateAlways = $200;
10181 {* Use this flag (in combination with others) to open existing or creating new
10182 file. If existing file is opened, it is truncated to size 0. }
10183 ofOpenExisting = $300;
10184 {* Use this flag (in combination with others) to open existing file only. }
10185 ofOpenAlways = $400;
10186 {* Use this flag (in combination with others) to open existing or create new
10187 (if such file is not yet exists). }
10188 ofTruncateExisting = $500;
10189 {* Use this flag (in combination with others) to open existing file and truncate
10190 it to size 0. }
10192 ofAttrReadOnly = $10000;
10193 {* Use this flag to create Read-Only file (?). }
10194 ofAttrHidden = $20000;
10195 {* Use this flag to create hidden file. }
10196 ofAttrSystem = $40000;
10197 {* Use this flag to create system file. }
10198 ofAttrTemp = $1000000;
10199 {* Use this flag to create temp file. }
10200 ofAttrArchive = $200000;
10201 {* Use this flag to create archive file. }
10202 ofAttrCompressed = $8000000;
10203 {* Use this flag to create compressed file. Has effect only on NTFS, and
10204 only if ofAttrCompressed is not specified also. }
10205 ofAttrOffline = $10000000;
10206 {* Use this flag to create offline file. }
10207 //[END OF OpenFileConstants]
10209 //[File FUNCTIONS DECLARATIONS]
10210 function FileCreate(const FileName: string; OpenFlags: DWord): THandle;
10211 {* Call this function to open existing or create new file. OpenFlags
10212 parameter can be a combination of up to three flags (by one from
10213 each group:
10214 |<table border=0>
10215 |&L=<tr><td valign=top>%0</td><td valign=top>
10216 |&E=</td></tr>
10217 <L ofOpenRead, ofOpenWrite, ofOpenReadWrite> - 1st group. Here You decide
10218 wish You open file for read, write or read-and-write operations; <E>
10219 <L ofShareExclusive, ofShareDenyWrite, ofShareDenyRead, ofShareDenyNone> -2nd
10220 group - sharing. Here You can mark out sharing mode, which is used to
10221 open file. <E>
10222 <L ofCreateNew, ofCreateAlways, ofOpenExisting, ofOpenAlways, ofTruncateExisting>
10223 - 3rd group - creation disposition. Here You determine, either to create new
10224 or open existing file and if to truncate existing or not.
10225 |</table> }
10226 function FileClose(Handle: THandle): Boolean;
10227 {* Call it to close opened earlier file. }
10228 function FileExists( const FileName: String ) : Boolean;
10229 {* Returns True, if given file exists.
10230 |<br>Note (by Dod):
10231 It is not documented in a help for GetFileAttributes, but it seems that
10232 under NT-based Windows systems, FALSE is always returned for files
10233 opened for excluseve use like pagefile.sys. }
10234 function FileRead(Handle: THandle; var Buffer; Count: DWord): DWord;
10235 {* Reads bytes from current position in file to buffer. Returns number of
10236 read bytes. }
10237 function File2Str(Handle: THandle): String;
10238 {* Reads file from current position to the end and returns result as ansi string. }
10240 function FileSeek(Handle: THandle; MoveTo: integer; MoveMethod: TMoveMethod): DWord;
10241 {* Changes current position in file. }
10242 function FileWrite(Handle: THandle; const Buffer; Count: DWord): DWord;
10243 {* Writes bytes from buffer to file from current position, extending its
10244 size if needed. }
10245 function FileEOF( Handle: THandle ) : Boolean;
10246 {* Returns True, if EOF is achieved during read operations or last byte is
10247 overwritten or append made to extend file during last write operation. }
10248 function FileFullPath( const FileName : String ) : String;
10249 {* Returns full path name for given file. Validness of source FileName path
10250 is not checked at all. }
10251 function FileShortPath( const FileName: String ): String;
10252 {* Returns short path to the file or directory. }
10253 function FileIconSystemIdx( const Path: String ): Integer;
10254 {* Returns index of the index of the system icon correspondent to the file or
10255 directory in system icon image list. }
10256 function FileIconSysIdxOffline( const Path: String ): Integer;
10257 {* The same as FileIconSystemIdx, but an icon is calculated for the file
10258 as it were offline (it is possible to get an icon for file even if
10259 it is not existing, on base of its extension only). }
10260 procedure LogFileOutput( const filepath, str: String );
10261 {* Debug function. Use it to append given string to the end of the given file. }
10263 function StrSaveToFile( const Filename, Str: String ): Boolean;
10264 {* Saves a string to a file without any changes. If file does not exists, it is
10265 created. If it exists, it is overriden. If operation failed, FALSE is returned. }
10266 function StrLoadFromFile( const Filename: String ): String;
10267 {* Reads entire file and returns its content as a string. If operation failed,
10268 an empty strinng is returned. }
10270 function Mem2File( Filename: PChar; Mem: Pointer; Len: Integer ): Integer;
10271 {* Saves memory block to a file (if file exists it is overriden, created new if
10272 not exists). }
10273 function File2Mem( Filename: PChar; Mem: Pointer; MaxLen: Integer ): Integer;
10274 {* Loads file content to memory. }
10276 function FileSize( const Path: String ) : Integer;
10277 {* Returns file size in bytes without opening it. If file too large
10278 to represent its size as Integer, -1 is returned. }
10279 function GetUniqueFilename( PathName: string ) : String;
10280 {* If file given by PathName exists, modifies it to create unique
10281 filename in target folder and returns it. Modification is performed
10282 by incrementing last number in name (if name part of file does not
10283 represent a number, such number is generated and concatenated to
10284 it). E.g., if file aaa.aaa is already exist, the function checks
10285 names aaa1.aaa, aaa2.aaa, ..., aaa10.aaa, etc. For name abc123.ext,
10286 names abc124.ext, abc125.ext, etc. will be checked. }
10288 function FileTimeCompare( const FT1, FT2 : TFileTime ) : Integer;
10289 {* Compares time of file (createing, writing, accessing. Returns
10290 -1, 0, 1 if correspondantly FT1<FT2, FT1=FT2, FT1>FT2. }
10292 //[Directory FUNCTIONS DECLARATIONS]
10293 function GetStartDir: String;
10294 {* Returns path to directory where executable is located (regardless
10295 of current directory). }
10296 function DirectoryExists(const Name: string): Boolean;
10297 {* Returns True if given directory (folder) exists. }
10298 function DirectoryEmpty(const Name: String): Boolean;
10299 {* Returns True if given directory is not exists or empty. }
10301 function DirectorySize( const Path: String ): I64;
10302 -- moved after PDirList
10304 function DirectoryHasSubdirs( const Path: String ): Boolean;
10305 {* Returns TRUE if given directory exists and has subdirectories. }
10306 function CheckDirectoryContent( const Name: String; SubDirsOnly: Boolean; const Mask: String ): Boolean;
10307 {* Returns TRUE if directory does not contain files (or directories only)
10308 satisfying given mask. }
10310 //---------------------------------------------------------
10311 // Following functions/procedures are created by Edward Aretino:
10312 // IncludeTrailingPathDelimiter, ExcludeTrailingPathDelimiter,
10313 // ForceDirectories, CreateDir, ChangeFileExt
10314 //---------------------------------------------------------
10315 function IncludeTrailingPathDelimiter(const S: string): string;
10316 {* by Edward Aretino. Adds '\' to the end if it is not present. }
10317 function ExcludeTrailingPathDelimiter(const S: string): string;
10318 {* by Edward Aretino. Removes '\' at the end if it is present. }
10319 function ForceDirectories(Dir: String): Boolean;
10320 {* by Edward Aretino. Creates given directory if not present. All needed
10321 subdirectories are created if necessary. }
10322 function CreateDir(const Dir: string): Boolean;
10323 {* by Edward Aretino. Creates given directory. }
10324 function ChangeFileExt(FileName: String; const Extension: string): string;
10325 {* by Edward Aretino. Changes file extention. }
10327 function ExcludeTrailingChar( const S: String; C: Char ): String;
10328 {* If S is finished with character C, it is excluded. }
10329 function IncludeTrailingChar( const S: String; C: Char ): String;
10330 {* If S is not finished with character C, it is added. }
10332 function ExtractFilePath( const Path: String ) : String;
10333 {* Returns only path part from exact path to file. }
10334 function ExtractFileName( const Path: String ) : String;
10335 {* Extracts file name from exact path to file. }
10336 function ExtractFileNameWOext( const Path: String ) : String;
10337 {* Extracts file name from path to file or from filename. }
10338 function ExtractFileExt( const Path: String ) : String;
10339 {* Extracts extention from file name (returns it with dot '.' first) }
10340 function ReplaceFileExt( const Path, NewExt: String ): String;
10341 {* Returns a path with extension replaced to a given one. }
10342 function ExtractShortPathName( const Path: String ): String;
10343 {* }
10344 function FilePathShortened( const Path: String; MaxLen: Integer ): String;
10345 {* Returns shortened file path to fit MaxLen characters. }
10346 function FilePathShortenPixels( const Path: String; DC: HDC; MaxPixels: Integer ): String;
10347 {* Returns shortened file path to fit MaxPixels for a given DC. If you pass
10348 Canvas.Handle of any control or bitmap object, ensure that font is valid
10349 for it (or call TCanvas.RequiredState( FontValid ) method before. If DC passed
10350 = 0, call is equivalent to call FilePathShortened, and MaxPixels means in such
10351 case maximum number of characters. }
10352 function MinimizeName( const Path: String; DC: HDC; MaxPixels: Integer ): String;
10353 {* Exactly the same as MinimizeName in FileCtrl.pas (VCL). }
10355 function GetSystemDir: String;
10356 {* Returns path to windows system directory. }
10357 function GetWindowsDir : string;
10358 {* Returns path to Windows directory. }
10359 function GetWorkDir : string;
10360 {* Returns path to application's working directory. }
10361 function GetTempDir : string;
10362 {* Returns path to default temp folder (directory to place temporary files). }
10363 function CreateTempFile( const DirPath, Prefix: String ): String;
10364 {* Returns path to just created temporary file. }
10365 function GetFileListStr(FPath{e.g.'c:\tmp\'}, FMask{e.g.'*.*'}: string): string;
10366 {* List of files in string, separating each path from others with semicolon (';').
10367 E.g.: 'c:\tmp\unit1.dcu;c:\tmp\unit1.~pa' (for use with DeleteFile2Recycle())}
10368 function DeleteFiles( const DirPath: String ): Boolean;
10369 {* Deletes files by file mask (given with wildcards '*' and '?'). }
10370 function DeleteFile2Recycle( const Filename : String ) : Boolean;
10371 {* Deletes file to recycle bin. This operation can be very slow, when
10372 called for a single file. To delete group of files at once (fast),
10373 pass a list of paths to files to be deleted, separating each path
10374 from others with semicolon (';'). E.g.: 'unit1.dcu;unit1.~pa'
10375 |<br>
10376 FALSE is returned only in case when at least one file was not deleted
10377 successfully.
10378 |<br>
10379 Note, that files are deleted not to recycle bin, if wildcards are
10380 used or not fully qualified paths to files. }
10381 function CopyMoveFiles( const FromList, ToList: String; Move: Boolean ): Boolean;
10382 {* }
10384 function DiskFreeSpace( const Path: String ): I64; {+}
10385 {* Returns disk free space in bytes. Pass a path to root directory,
10386 e.g. 'C:\'.
10387 |<hr>
10398 <R Wrappers to registry API functions>
10400 These functions can be used independently to simplify access to Windows
10401 registry. }
10403 //[Registry FUNCTIONS DECLARATIONS]
10404 {++}(*
10405 function RegSetValueEx(hKey: HKEY; lpValueName: PChar;
10406 Reserved: DWORD; dwType: DWORD; lpData: Pointer; cbData: DWORD): Longint; stdcall;
10407 *){--}
10408 function RegKeyOpenRead( Key: HKey; const SubKey: String ): HKey;
10409 {* Opens registry key for read operations (including enumerating of subkeys).
10410 Pass either handle of opened earlier key or one of constans
10411 HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_USERS
10412 as a first parameter. If not successful, 0 is returned. }
10413 function RegKeyOpenWrite( Key: HKey; const SubKey: String ): HKey;
10414 {* Opens registry key for write operations (including adding new values or
10415 subkeys), as well as for read operations too. See also RegKeyOpenRead. }
10416 function RegKeyOpenCreate( Key: HKey; const SubKey: String ): HKey;
10417 {* Creates and opens key. }
10418 function RegKeyGetStr( Key: HKey; const ValueName: String ): String;
10419 {* Reads key, which must have type REG_SZ (null-terminated string). If
10420 not successful, empty string is returned. This function as well as all
10421 other registry manipulation functions, does nothing, if Key passed is 0
10422 (without producing any error). }
10423 function RegKeyGetStrEx( Key: HKey; const ValueName: String ): String;
10424 {* Like RegKeyGetStr, but accepts REG_EXPAND_SZ type, expanding all
10425 environment variables in resulting string.
10426 |<br>
10427 Code provided by neuron, e-mailto:neuron@hollowtube.mine.nu }
10428 function RegKeyGetDw( Key: HKey; const ValueName: String ): DWORD;
10429 {* Reads key value, which must have type REG_DWORD. If ValueName passed
10430 is '' (empty string), unnamed (default) value is reading. If not
10431 successful, 0 is returned. }
10432 function RegKeySetStr(Key: HKey; const ValueName: String; const Value: String ): Boolean;
10433 {* Writes new key value as null-terminated string (type REG_SZ). If not
10434 successful, returns False. }
10435 function RegKeySetStrEx( Key: HKey; const ValueName: string; const Value: string;
10436 expand: boolean): Boolean;
10437 {* Writes new key value as REG_SZ or REG_EXPAND_SZ. - by neuron, e-mailto:neuron@hollowtube.mine.nu }
10438 function RegKeySetDw( Key: HKey; const ValueName: String; Value: DWORD ): Boolean;
10439 {* Writes new key value as dword (with type REG_DWORD). Returns False,
10440 if not successful. }
10441 procedure RegKeyClose( Key: HKey );
10442 {* Closes key, opened using RegKeyOpenRead or RegKeyOpenWrite. (But does
10443 nothing, if Key passed is 0). }
10444 function RegKeyDelete( Key: HKey; const SubKey: String ): Boolean;
10445 {* Deletes key. Does nothing if key passed is 0 (returns FALSE). }
10446 function RegKeyDeleteValue( Key: HKey; const SubKey: String ): Boolean;
10447 {* Deletes value. - by neuron, e-mailto:neuron@hollowtube.mine.nu }
10448 function RegKeyExists( Key: HKey; const SubKey: String ): Boolean;
10449 {* Returns TRUE, if given subkey exists under given Key. }
10450 function RegKeyValExists( Key: HKey; const ValueName: String ): Boolean;
10451 {* Returns TRUE, if given value exists under the Key.
10453 function RegKeyValueSize( Key: HKey; const ValueName: String ): Integer;
10454 {* Returns a size of value. This is a size of buffer needed to store
10455 registry key value. For string value, size returned is equal to a
10456 length of string plus 1 for terminated null character. }
10457 function RegKeyGetBinary( Key: HKey; const ValueName: String; var Buffer; Count: Integer ): Integer;
10458 {* Reads binary data from a registry, writing it to the Buffer.
10459 It is supposed that size of Buffer provided is at least Count bytes.
10460 Returned value is actul count of bytes read from the registry and written
10461 to the Buffer.
10462 |<br>
10463 This function can be used to get data of any type from the registry, not
10464 only REG_BINARY. }
10465 function RegKeySetBinary( Key: HKey; const ValueName: String; const Buffer; Count: Integer ): Boolean;
10466 {* Stores binary data in the registry. }
10467 function RegKeyGetDateTime(Key: HKey; const ValueName: String): TDateTime;
10468 {* Returns datetime variable stored in registry in binary format. }
10469 function RegKeySetDateTime(Key: HKey; const ValueName: String; DateTime: TDateTime): Boolean;
10470 {* Stores DateTime variable in the registry. }
10473 //-------------------------------------------------------
10474 // registry functions by Valerian Luft <luft@valerian.de>
10475 //-------------------------------------------------------
10476 function RegKeyGetSubKeys( const Key: HKEY; List: PStrList): Boolean;
10477 {* The function enumerates subkeys of the specified open registry key.
10478 True is returned, if successful.
10480 function RegKeyGetValueNames(const Key: HKEY; List: PStrList): Boolean;
10481 {* The function enumerates value names of the specified open registry key.
10482 True is returned, if successful.
10484 function RegKeyGetValueTyp (const Key:HKEY; const ValueName: String) : DWORD;
10485 {* The function receives the type of data stored in the specified value.
10486 |<br>
10487 If the function fails, the return value is the Key value.
10488 |<br>
10489 If the function succeeds, the return value return will be one of the following:
10490 |<br>
10491 REG_BINARY , REG_DWORD, REG_DWORD_LITTLE_ENDIAN,
10492 REG_DWORD_BIG_ENDIAN, REG_EXPAND_SZ, REG_LINK , REG_MULTI_SZ,
10493 REG_NONE, REG_RESOURCE_LIST, REG_SZ
10496 |<hr>
10516 <R Data sorting (quicksort implementation)>
10517 This part contains implementation of 'quick sort' algorithm,
10518 based on following code:
10520 |<pre>
10521 | TQSort by Mike Junkin 10/19/95.
10522 | DoQSort routine adapted from Peter Szymiczek's QSort procedure which
10523 | was presented in issue#8 of The Unofficial Delphi Newsletter.
10525 | TQSort changed by Vladimir Kladov (Mr.Bonanzas) to allow 32-bit
10526 | sorting (of big arrays with more than 64K elements).
10527 |</pre>
10529 Finally, this sort procedure is adapted to XCL (and then to KOL)
10530 requirements (no references to SysUtils, Classes etc. TQSort object
10531 is transferred to a single procedure call and DoQSort method is
10532 renamed to SortData - which is a regular procedure now). }
10534 //[Sorting TYPES]
10535 type
10536 TCompareEvent = function (const Data: Pointer; const e1,e2 : Dword) : Integer;
10537 {* Event type to define comparison function between two elements of an array.
10538 This event handler must return -1 or +1 (correspondently for cases e1<e2
10539 and e2>e2). Items are enumerated from 0 to uNElem. }
10540 TSwapEvent = procedure (const Data : Pointer; const e1,e2 : Dword);
10541 {* Event type to define swap procedure which is swapping two elements of an
10542 array. }
10544 //[SortData FUNCTIONS DECLARATIONS]
10545 procedure SortData( const Data: Pointer; const uNElem: Dword;
10546 const CompareFun: TCompareEvent;
10547 const SwapProc: TSwapEvent );
10548 {* Call it to sort any array of data of any kind, passing total
10549 number of items in an array and two defined (regular) function
10550 and procedure to perform custom compare and swap operations.
10551 First procedure parameter is to pass it to callback function
10552 CompareFun and procedure SwapProc. Items are enumerated from
10553 0 to uNElem-1. }
10555 procedure SortIntegerArray( var A : array of Integer );
10556 {* procedure to sort array of integers. }
10558 procedure SortDwordArray( var A : array of DWORD );
10559 {* Procedure to sort array of unsigned 32-bit integers.
10560 |<hr>
10575 { -- directory list object -- }
10576 //[DirList Object]
10578 type
10579 TDirItemAction = ( diSkip, diAccept, diCancel );
10580 TOnDirItem = procedure( Sender: PObj; var DirItem: TWin32FindData; var Accept: TDirItemAction )
10581 of object;
10582 TSortDirRules = ( sdrNone, sdrFoldersFirst, sdrCaseSensitive, sdrByName, sdrByExt,
10583 sdrBySize, sdrBySizeDescending, sdrByDateCreate, sdrByDateChanged,
10584 sdrByDateAccessed );
10585 {* List of rules (options) to sort directories. Rules are passed to Sort
10586 method in an array, and first placed rules are applied first. }
10588 {++}(*TDirList = class;*){--}
10589 PDirList = {-}^{+}TDirList;
10590 { ----------------------------------------------------------------------
10592 TDirList - Directory scanning
10594 ----------------------------------------------------------------------- }
10595 //[TDirList DEFINITION]
10596 TDirList = object( TObj )
10597 {* Allows easy directory scanning. This is not visual object, but
10598 storage to simplify working with directory content. }
10599 protected
10600 FList : PList;
10601 FPath: string;
10602 fFilters: PStrList;
10603 fOnItem: TOnDirItem;
10604 function Get(Idx: Integer): PWin32FindData;
10605 function GetCount: Integer;
10606 function GetNames(Idx: Integer): string;
10607 function GetIsDirectory(Idx: Integer): Boolean;
10608 protected
10609 function SatisfyFilter( FileName : PChar; FileAttr, FindAttr : DWord ) : Boolean;
10610 {++}(*public*){--}
10611 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
10612 {* Destructor. As usual, call Free method to destroy an object. }
10613 public
10614 property Items[ Idx : Integer ] : PWin32FindData read Get; default;
10615 {* Full access to scanned items (files and subdirectories). }
10616 property IsDirectory[ Idx: Integer ]: Boolean read GetIsDirectory;
10617 {* Returns TRUE, if specified item represents a directory, not a file. }
10618 property Count : Integer read GetCount;
10619 {* Number of items. }
10620 property Names[ Idx : Integer ] : string read GetNames;
10621 {* Full long names of directory items. }
10622 property Path : string read FPath;
10623 {* Path of scanned directory. }
10624 procedure Clear;
10625 {* Call it to clear list of files. }
10626 procedure ScanDirectory( const DirPath, Filter : String; Attr : DWord );
10627 {* Call it to rescan directory or to scan another directory content
10628 (method Clear is called first). Pass path to directory, file filter
10629 and attributes to scan directory immediately.
10630 |<br>&nbsp;&nbsp;&nbsp;
10631 Note: Pass FILE_ATTRIBUTE_... constants or-combination as Attr
10632 parameter. If 0 passed, both files and directories are listed. }
10633 procedure ScanDirectoryEx( const DirPath, Filters : String; Attr : DWord );
10634 {* Call it to rescan directory or to scan another directory content
10635 (method Clear is called first). Pass path to directory, file filter
10636 and attributes to scan directory immediately.
10637 |<br>&nbsp;&nbsp;&nbsp;
10638 Note: Pass FILE_ATTRIBUTE_... constants or-combination as Attr
10639 parameter. }
10640 procedure Sort( Rules : array of TSortDirRules );
10641 {* Sorts directory entries. If empty rules array passed, default rules
10642 array DefSortDirRules is used. }
10643 function FileList( const Separator {e.g.: ';', or #13}: String;
10644 Dirs, FullPaths: Boolean ): String;
10645 {* Returns a string containing all names separated with Separator.
10646 If Dirs=FALSE, only files are returned. }
10647 property OnItem: TOnDirItem read fOnItem write fOnItem;
10648 {* This event is called on reading each item while scanning directory.
10649 To use it, first create PDirList object with empty path to scan, then
10650 assign OnItem event and call ScanDirectory with correct path. }
10651 end;
10652 //[END OF TDirList DEFINITION]
10654 //[NewDirList DECLARATIONS]
10655 function NewDirList( const DirPath, Filter: String; Attr: DWORD ): PDirList;
10656 {* Creates directory list object using easy one-string filter. If Attr = FILE_ATTRIBUTE_NORMAL,
10657 only files are scanned without directories. If Attr = 0, both files and
10658 directories are listed. }
10660 function NewDirListEx( const DirPath, Filters: String; Attr: DWORD ): PDirList;
10661 {* Creates directory list object using several filters, separated by ';'.
10662 Filters starting from '^' consider to be anti-filters, i.e. files,
10663 satisfying to those masks, are skept during scanning. }
10665 const DefSortDirRules : array[ 0..3 ] of TSortDirRules = ( sdrFoldersFirst,
10666 sdrByName, sdrBySize, sdrByDateCreate );
10667 {* Default rules to sort directory entries. }
10669 //[DirectorySize DECLARATION]
10671 function DirectorySize( const Path: String ): I64;
10672 {* Returns directory size in bytes as large 64 bit integer. }
10676 //[OpenSaveDialog OPTIONS]
10677 type
10678 TOpenSaveOption = ( OSCreatePrompt,
10679 OSExtensionDiffent,
10680 OSFileMustExist,
10681 OSHideReadonly,
10682 OSNoChangedir,
10683 OSNoReferenceLinks,
10684 OSAllowMultiSelect,
10685 OSNoNetworkButton,
10686 OSNoReadonlyReturn,
10687 OSOverwritePrompt,
10688 OSPathMustExist,
10689 OSReadonly,
10690 OSNoValidate
10691 //{$IFDEF OpenSaveDialog_Extended}
10693 OSTemplate,
10694 OSHook
10695 //{$ENDIF}
10697 TOpenSaveOptions = set of TOpenSaveOption;
10698 {* Options available for TOpenSaveDialog. }
10700 {++}(*TOpenSaveDialog = class;*){--}
10701 POpenSaveDialog = {-}^{+}TOpenSaveDialog;
10702 { ----------------------------------------------------------------------
10704 TOpenSaveDialog
10706 ----------------------------------------------------------------------- }
10707 //[TOpenSaveDialog DEFINITION]
10708 TOpenSaveDialog = object( TObj )
10709 {* Object to show standard Open/Save dialog. Initially provided
10710 for XCL by Carlo Kok. }
10711 protected
10712 FFilter : String;
10713 fFilterIndex : Integer;
10714 fOpenDialog : Boolean;
10715 FInitialDir : String;
10716 FDefExtension : String;
10717 FFilename : string;
10718 FTitle : string;
10719 FOptions : TOpenSaveOptions;
10720 fWnd: THandle;
10721 public
10722 {$IFDEF OpenSaveDialog_Extended}
10723 TemplateName: String;
10724 HookProc: Pointer;
10725 {$ENDIF}
10726 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
10727 {* destructor }
10728 Function Execute : Boolean;
10729 {* Call it after creating to perform selecting of file by user. }
10730 property Filename : String read FFilename write FFileName;
10732 Filename is seperated by #13 when multiselect is true and the first
10733 file, is the path of the files selected.
10734 |<pre>
10735 | C:\Projects
10736 | Test1.Dpr
10737 | Test2.Dpr
10738 |</pre>
10739 If only one file is selected, it is provided as (e.g.)
10740 C:\Projects\Test1.dpr
10741 |<br> For case when OSAllowMultiselect option used, after each
10742 call initial value for a Filename containing several files prevents
10743 system from opening the dialog. To fix this, assign another initial
10744 value to Filename property in your code, when you use multiselect.
10746 property InitialDir : string read FInitialDir write FInitialDir;
10747 {* Initial directory path. If not set, current directory (usually
10748 directory when program is started) is used. }
10749 property Filter : String read FFilter write FFilter;
10750 {* A list of pairs of filter names and filter masks, separated with '|'.
10751 If a mask contains more than one mask, it should be separated with ';'.
10752 E.g.:
10753 ! 'All files|*.*|Text files|*.txt;*.1st;*.diz' }
10754 property FilterIndex : Integer read FFilterIndex write FFilterIndex;
10755 {* Index of default filter mask (0 by default, which means "first"). }
10756 property OpenDialog : Boolean read FOpenDialog write FOpenDialog;
10757 {* True, if "Open" dialog. False, if "Save" dialog. True is default. }
10758 property Title : String read Ftitle write Ftitle;
10759 {* Title for dialog. }
10760 property Options : TOpenSaveOptions read FOptions write FOptions;
10761 {* Options. }
10762 property DefExtension : String read FDefExtension write FDefExtension;
10763 {* Default extention. Set it to desired extension without leading period,
10764 e.g. 'txt', but not '.txt'. }
10765 property WndOwner: THandle read fWnd write fWnd;
10766 {* Owner window handle. If not assigned, Applet.Handle is used (whenever
10767 possible). Assign it, if your application has stay-on-top forms, and
10768 a separate Applet object is used. }
10769 end;
10770 //[END OF TOpenSaveDialog DEFINITION]
10772 //[Default OpenSaveDialog OPTIONS]
10773 const DefOpenSaveDlgOptions: TOpenSaveOptions = [ OSHideReadonly,
10774 OSOverwritePrompt, OSFileMustExist, OSPathMustExist ];
10776 //[NewOpenSaveDialog DECLARATION]
10777 function NewOpenSaveDialog( const Title, StrtDir: String;
10778 Options: TOpenSaveOptions ): POpenSaveDialog;
10779 {* Creates object, which can be used (several times) to open file(s)
10780 selecting dialog. }
10784 //[OpenDirectory Object]
10785 type
10786 {++}(*TOpenDirDialog = class;*){--}
10787 POpenDirDialog = {-}^{+}TOpenDirDialog;
10789 TOpenDirOption = ( odBrowseForComputer, odBrowseForPrinter, odDontGoBelowDomain,
10790 odOnlyFileSystemAncestors, odOnlySystemDirs, odStatusText,
10791 odBrowseIncludeFiles );
10792 {* Flags available for TOpenDirDialog object. }
10793 // odfStatusText - do not support status callback
10794 TOpenDirOptions = set of TOpenDirOption;
10795 {* Set of all flags used to control ZOpenDirDialog class. }
10797 TOnODSelChange = procedure( Sender: POpenDirDialog; NewSelDir: PChar;
10798 var EnableOK: Integer; var StatusText: String )
10799 of object;
10800 {* Event type to be called when user select another directory in OpenDirDialog.
10801 Set EnableOK to -1 to disable OK button, or to +1 to enable it.
10802 It is also possible to set new StatusText string. }
10804 { ----------------------------------------------------------------------
10806 TOpenDirDialog
10808 ----------------------------------------------------------------------- }
10809 //[TOpenDirDialog DEFINITION]
10810 TOpenDirDialog = object( TObj )
10811 {* Dialog for open directories, uses SHBrowseForFolder. }
10812 protected
10813 FTitle: String;
10814 FOptions: TOpenDirOptions;
10815 FCallBack: Pointer;
10816 FCenterProc: procedure( Wnd: HWnd );
10817 FBuf : array[ 0..MAX_PATH ] of Char;
10818 FInitialPath: String;
10819 FCenterOnScreen: Boolean;
10820 FDoSelChanged: procedure( Wnd: HWnd; Msg: DWORD; lParam, lpData: LParam ); stdcall;
10821 FOnSelChanged: TOnODSelChange;
10822 FStatusText: String;
10823 FWnd: HWnd;
10824 function GetPath: String;
10825 procedure SetInitialPath(const Value: String);
10826 procedure SetCenterOnScreen(const Value: Boolean);
10827 procedure SetOnSelChanged(const Value: TOnODSelChange);
10828 function GetInitialPath: String;
10829 public
10830 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
10831 {* destructor }
10832 function Execute : Boolean;
10833 {* Call it to select directory by user. Returns True, if operation was
10834 not cancelled by user. }
10835 property Title : String read FTitle write FTitle;
10836 {* Title for a dialog. }
10837 property Options : TOpenDirOptions read FOptions write FOptions;
10838 {* Option flags. }
10839 property Path : String read GetPath;
10840 {* Resulting (selected by user) path. }
10841 property InitialPath: String read GetInitialPath write SetInitialPath;
10842 {* Set this property to a path of directory to be selected initially
10843 in a dialog. }
10844 property CenterOnScreen: Boolean read FCenterOnScreen write SetCenterOnScreen;
10845 {* Set it to True to center dialog on screen. }
10846 property OnSelChanged: TOnODSelChange read FOnSelChanged write SetOnSelChanged;
10847 {* This event is called every time, when user selects another directory.
10848 It is possible to eneble/disable OK button in dialog and/or change
10849 dialog status text in responce to event. }
10850 property WndOwner: HWnd read FWnd write FWnd;
10851 {* Owner window. If you want to provide your dialog visible over stay-on-top
10852 form, fire it as a child of the form, assigning the handle of form window
10853 to this property first. }
10854 end;
10855 //[END OF TOpenDirDialog DEFINITION]
10857 //[NewOpenSaveDialog DECLARATION]
10858 function NewOpenDirDialog( const Title: String; Options: TOpenDirOptions ):
10859 POpenDirDialog;
10860 {* Creates object, which can be used (several times) to open directory
10861 selecting dialog (using SHBrowseForFolder API call). }
10871 //[Color Dialog Object]
10872 type
10873 TColorCustomOption = ( ccoFullOpen, ccoShortOpen, ccoPreventFullOpen );
10875 {++}(*TColorDialog = class;*){--}
10876 PColorDialog = {-}^{+}TColorDialog;
10877 { ----------------------------------------------------------------------
10879 TColorDialog
10881 ----------------------------------------------------------------------- }
10882 //[TColorDialog DEFINITION]
10883 TColorDialog = object( TObj )
10884 {* Color choosing dialog. }
10885 protected
10886 public
10887 OwnerWindow: HWnd;
10888 {* Owner window (can be 0). }
10889 CustomColors: array[ 1..16 ] of TColor;
10890 {* Array of stored custom colors. }
10891 ColorCustomOption: TColorCustomOption;
10892 {* Options (how to open a dialog). }
10893 Color: TColor;
10894 {* Returned color (if the result of Execute is True). }
10895 function Execute: Boolean;
10896 {* Call this method to open a dialog and wait its result. }
10897 end;
10898 //[END OF TColorDialog DEFINITION]
10900 //[NewColorDialog DECLARATION]
10901 function NewColorDialog( FullOpen: TColorCustomOption ): PColorDialog;
10902 {* Creates color choosing dialog object. }
10912 //[Ini files]
10913 type
10914 TIniFileMode = ( ifmRead, ifmWrite );
10915 {* ifmRead is default mode (means "read" data from ini-file.
10916 Set mode to ifmWrite to write data to ini-file, correspondent to
10917 TIniFile. }
10919 {++}(*TIniFile = class;*){--}
10920 PIniFile = {-}^{+}TIniFile;
10921 { ----------------------------------------------------------------------
10923 TIniFile - store/load data to ini-files
10925 ----------------------------------------------------------------------- }
10926 //[TIniFile DEFINITION]
10927 TIniFile = object( TObj )
10928 {* Ini file incapsulation. The main feature is what the same block of
10929 read-write operations could be defined (difference must be only in
10930 Mode value).
10931 |*Ini file sample.
10932 This sample shows how the same Pascal operators can be used both
10933 for read and write for the same variables, when working with TIniFile:
10934 ! procedure ReadWriteIni( Write: Boolean );
10935 ! var Ini: PIniFile;
10936 ! begin
10937 ! Ini := OpenIniFile( 'MyIniFile.ini' );
10938 ! Ini.Section := 'Main';
10939 ! if Write then // if Write, the same operators will save
10940 ! Ini.Mode := ifmWrite; // data rather then load.
10941 ! MyForm.Left := Ini.ValueInteger( 'Left', MyForm.Left );
10942 ! MyForm.Top := Ini.ValueInteger( 'Top', MyForm.Top );
10943 ! Ini.Free;
10944 ! end;
10946 |* }
10947 protected
10948 fMode: TIniFileMode;
10949 fFileName: String;
10950 fSection: String;
10951 protected
10952 public
10953 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
10954 {* destructor }
10955 property Mode: TIniFileMode read fMode write fMode;
10956 {* ifmWrite, if write data to ini-file rather than read it. }
10957 property FileName: String read fFileName;
10958 {* Ini file name. }
10959 property Section: String read fSection write fSection;
10960 {* Current ini section. }
10961 function ValueInteger( const Key: String; Value: Integer ): Integer;
10962 {* Reads or writes integer data value. }
10963 function ValueString( const Key: String; const Value: String ): String;
10964 {* Reads or writes string data value. }
10965 function ValueBoolean( const Key: String; Value: Boolean ): Boolean;
10966 {* Reads or writes boolean data value. }
10967 function ValueData( const Key: String; Value: Pointer; Count: Integer ): Boolean;
10968 {* Reads or writes data from/to buffer. Returns True, if success. }
10969 procedure ClearAll;
10970 {* Clears all sections of ini-file. }
10971 procedure ClearSection;
10972 {* Clears current Section of ini-file. }
10973 procedure ClearKey( const Key: String );
10974 {* Clears given key in current section. }
10976 /////////////// + by Vyacheslav A. Gavrik:
10977 procedure GetSectionNames(Names:PStrList);
10978 {* Retrieves section names, storing it in string list passed as a parameter.
10979 String list does not cleared before processing. Section names are added
10980 to the end of the string list. }
10981 procedure SectionData(Names:PStrList);
10982 {* Read/write current section content to/from string list. (Depending on
10983 current Mode value). }
10984 ///////////////
10986 end;
10987 //[END OF TIniFile DEFINITION]
10989 //[OpenIniFile DECLARATION]
10990 function OpenIniFile( const FileName: String ): PIniFile;
10991 {* Opens ini file, creating TIniFile object instance to work with it. }
10997 //[CABINET FILES OBJECT]
10998 type
10999 {++}(*TCabFile = class;*){--}
11000 PCABFile = {-}^{+}TCABFile;
11002 TOnNextCAB = function( Sender: PCABFile ): String of object;
11003 TOnCABFile = function( Sender: PCABFile; var FileName: String ): Boolean of object;
11005 { ----------------------------------------------------------------------
11007 TCabFile - windows cabinet files
11009 ----------------------------------------------------------------------- }
11010 //[TCabFile DEFINITION]
11011 TCABFile = object( TObj )
11012 {* An object to simplify extracting files from a cabinet (.CAB) files.
11013 The only what need to use this object, setupapi.dll. It is provided
11014 with all latest versions of Windows. }
11015 protected
11016 FPaths: PStrList;
11017 FNames: PStrList;
11018 FOnNextCAB: TOnNextCAB;
11019 FOnFile: TOnCABFile;
11020 FTargetPath: String;
11021 FSetupapi: THandle;
11022 function GetNames(Idx: Integer): String;
11023 function GetCount: Integer;
11024 function GetPaths(Idx: Integer): String;
11025 function GetTargetPath: String;
11026 protected
11027 FGettingNames: Boolean;
11028 FCurCAB: Integer;
11029 public
11030 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
11031 {* }
11032 property Paths[ Idx: Integer ]: String read GetPaths;
11033 {* A list of CAB-files. It is stored, when constructing function
11034 OpenCABFile called. }
11035 property Names[ Idx: Integer ]: String read GetNames;
11036 {* A list of file names, stored in a sequence of CAB files. To get know,
11037 how many files are there, check Count property. }
11038 property Count: Integer read GetCount;
11039 {* Number of files stored in a sequence of CAB files. }
11040 function Execute: Boolean;
11041 {* Call this method to extract or enumerate files in CAB. For every
11042 file, found during executing, event OnFile is alled (if assigned).
11043 If the event handler (if any) does not provide full target path for
11044 a file to extract to, property TargetPath is applyed (also if it
11045 is assigned), or file is extracted to the default directory (usually
11046 the same directory there CAB file is located, or current directory
11047 - by a decision of the system).
11048 |<br>
11049 If a sequence of CAB files is used, and not all names for CAB files
11050 are provided (absent or represented by a string '?' ), an event
11051 OnNextCAB is called to obtain the name of the next CAB file.}
11052 property CurCAB: Integer read FCurCAB;
11053 {* Index of current CAB file in a sequence of CAB files. When OnNextCAB
11054 event is called (if any), CurCAB property is already set to the
11055 index of path, what should be provided. }
11056 property OnNextCAB: TOnNextCAB read FOnNextCAB write FOnNextCAB;
11057 {* This event is called, when a series of CAB files is needed and not
11058 all CAB file names are provided (absent or represented by '?' string).
11059 If this event is not assigned, the user is prompted to browse file. }
11060 property OnFile: TOnCABFile read FOnFile write FOnFile;
11061 {* This event is called for every file found during Execute method.
11062 In an event handler (if any assigned), it is possible to return
11063 False to skip file, or to provide another full target path for
11064 file to extract it to, then default. If the event is not assigned,
11065 all files are extracted either to default directory, or to the
11066 directory TargetPath, if it is provided. }
11067 property TargetPath: String read GetTargetPath write FTargetPath;
11068 {* Optional target directory to place there extracted files. }
11069 end;
11070 //[END OF TCABFile DEFINITION]
11072 //[OpenCABFile DECLARATION]
11073 function OpenCABFile( const APaths: array of String ): PCABFile;
11074 {* This function creates TCABFile object, passing a sequence of CAB file names
11075 (fully qualified). It is possible not to provide all names here, or pass '?'
11076 string in place of some of those. For such files, either an event OnNextCAB
11077 will be called, or (and) user will be prompted to browse file during
11078 executing (i.e. Extracting). }
11086 //[MENU OBJECT]
11088 type
11089 TMenuitemInfo = packed record
11090 cbSize: UINT;
11091 fMask: UINT;
11092 fType: UINT; { used if MIIM_TYPE}
11093 fState: UINT; { used if MIIM_STATE}
11094 wID: UINT; { used if MIIM_ID}
11095 hSubMenu: HMENU; { used if MIIM_SUBMENU}
11096 hbmpChecked: HBITMAP; { used if MIIM_CHECKMARKS}
11097 hbmpUnchecked: HBITMAP; { used if MIIM_CHECKMARKS}
11098 dwItemData: DWORD; { used if MIIM_DATA}
11099 dwTypeData: PAnsiChar; { used if MIIM_TYPE}
11100 cch: UINT; { used if MIIM_TYPE}
11101 hbmpItem: HBITMAP; { used if MIIM_BITMAP - not exists under Windows95 }
11102 end;
11104 type
11105 {++}(*TMenu = class;*){--}
11106 PMenu = {-}^{+}TMenu;
11108 TOnMenuItem = procedure( Sender : PMenu; Item : Integer ) of object;
11109 {* Event type to define OnMenuItem event. }
11111 TMenuAccelerator = packed Record
11112 {* Menu accelerator record. Use MakeAccelerator function to combine desired
11113 attributes into a record, describing the accelerator. }
11114 fVirt: Byte; // or-combination of FSHIFT, FCONTROL, FALT, FVIRTKEY, FNOINVERT
11115 Key: Word; // character or virtual key code (FVIRTKEY flag is present above)
11116 NotUsed: Byte; // not used
11117 end;
11119 // by Sergey Shisminzev:
11120 TMenuOption = (moDefault, moDisabled, moChecked,
11121 moCheckMark, moRadioMark, moSeparator, moBitmap, moSubMenu,
11122 moBreak, moBarBreak);
11123 {* Options to add menu items dynamically. }
11124 TMenuOptions = set of TMenuOption;
11125 {* Set of options for menu item to use it in TMenu.AddItem method. }
11127 TMenuBreak = ( mbrNone, mbrBreak, mbrBarBreak );
11128 {* Possible menu item break types. }
11130 { ----------------------------------------------------------------------
11132 TMenu - main, popup menu and menu item
11134 ----------------------------------------------------------------------- }
11135 //[TMenu DEFINITION]
11136 TMenu = object( TObj )
11137 {* Dynamic menu incapsulation object. Can play role of form main menu or popup
11138 menu, depending on kind of parent window (form or control) and order of
11139 creation (created first (for a form) become main menu). Does not allow
11140 merging menus, but items can be hidden. Additionally checkmark bitmaps,
11141 shortcut key accelerators and other features are available. }
11142 protected
11143 FHandle: HMenu;
11144 FId: Integer;
11145 FParent: PMenu;
11146 FControl: PControl;
11147 fNextMenu : PMenu;
11148 FRadioGroup: Integer;
11149 FIsCheckItem: Boolean;
11150 FIsSeparator: Boolean;
11151 FMenuBreak: TMenuBreak;
11152 FItems: PList;
11153 FOnMenuItem : TOnMenuItem;
11154 FOnRadioOff : TOnMenuItem;
11155 fOnPopup: TOnEvent;
11156 fByAccel: Boolean;
11157 FPopupFlags: DWORD;
11158 //fAutoPopup: Boolean;
11159 FVisible: Boolean;
11160 FSavedState: DWORD;
11161 FData: Pointer;
11162 FOwnerDraw: Boolean;
11163 FCaption: String;
11164 FBitmap: HBitmap;
11165 FBmpChecked: HBitmap;
11166 FBmpItem: HBitmap;
11167 ClearBitmapsProc: procedure( Sender: PMenu );
11168 FClearBitmaps: Boolean;
11169 FNotPopup: Boolean;
11170 FAccelerator: TMenuAccelerator;
11171 FHelpContext: Integer;
11172 FOnMeasureItem: TOnMeasureItem;
11173 FOnDrawItem: TOnDrawItem;
11174 {$IFDEF USE_MENU_CURCTL}
11175 fCurCtl: PControl;
11176 {$ENDIF USE_MENU_CURCTL}
11177 function GetItems( Id: HMenu ): PMenu;
11178 function GetCount: Integer;
11179 function GetTopParent: PMenu;
11180 function GetState( const Index: Integer ): Boolean;
11181 procedure SetState( const Index: Integer; Value: Boolean );
11182 procedure SetVisible( Value: Boolean );
11183 procedure SetData( Value: Pointer );
11184 procedure SetMenuItemCaption( const Value: String );
11185 function FillMenuItems(AHandle: HMenu; StartIdx: Integer;
11186 const Template: array of PChar): Integer;
11187 procedure SetMenuBreak( Value: TMenuBreak );
11188 function GetControl: PControl;
11189 function GetInfo( var MII: TMenuItemInfo ): Boolean;
11190 function SetInfo( var MII: TMenuItemInfo ): Boolean;
11191 function SetTypeInfo( var MII: TMenuItemInfo ): Boolean;
11192 procedure SetBitmap( Value: HBitmap );
11193 procedure SetBmpChecked( Value: HBitmap );
11194 procedure SetBmpItem( Value: HBitmap );
11195 procedure ClearBitmaps;
11196 procedure SetAccelerator( const Value: TMenuAccelerator );
11197 procedure SetHelpContext( Value: Integer );
11198 procedure SetSubmenu( Value: HMenu );
11199 procedure SetOnMeasureItem( const Value: TOnMeasureItem );
11200 procedure SetOnDrawItem( const Value: TOnDrawItem );
11201 procedure SetOwnerDraw( Value: Boolean );
11202 protected
11203 function GetItemChecked( Item : Integer ) : Boolean;
11204 procedure SetItemChecked( Item : Integer; Value : Boolean );
11205 function GetItemBitmap(Idx: Integer): HBitmap;
11206 procedure SetItemBitmap(Idx: Integer; const Value: HBitmap);
11207 function GetItemText(Idx: Integer): String;
11208 procedure SetItemText(Idx: Integer; const Value: String);
11209 function GetItemEnabled(Idx: Integer): Boolean;
11210 procedure SetItemEnabled(Idx: Integer; const Value: Boolean);
11211 function GetItemVisible(Idx: Integer): Boolean;
11212 procedure SetItemVisible(Idx: Integer; const Value: Boolean);
11213 function GetItemAccelerator(Idx: Integer): TMenuAccelerator;
11214 procedure SetItemAccelerator(Idx: Integer; const Value: TMenuAccelerator);
11215 function GetItemSubMenu( Idx: Integer ): HMenu;
11216 public
11217 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
11218 {* To release menu dynamically, call Free method instead. All (popup)
11219 menus created after this (for the same control) are destroyed in
11220 that case too.
11221 |<br>
11222 It is not necessary to release menu object manually: all menus,
11223 created with given form (or control), are automatically released,
11224 when owner form (or control) is destroyed.
11226 property Handle : HMenu read FHandle;
11227 {* Handle of Windows menu object. }
11228 property MenuId: Integer read FId;
11229 {* Id of the menu item object. If menu item has subitems, it has
11230 also submenu Handle. Top parent menu object itself has no Id.
11231 Id-s areassigned automatically starting from 4096. Do not
11232 (re)create menu items instantly, because such values are not
11233 reused, and maximum possible Id value must not exceed 65535. }
11234 property Parent: PMenu read FParent;
11235 {* Parent menu item (or parent menu). }
11236 property TopParent: PMenu read GetTopParent;
11237 {* Top parent menu, owning all nested subitems. }
11238 property Owner: PControl read GetControl;
11239 {* Parent control or form. }
11240 property Caption: String read FCaption write SetMenuItemCaption;
11241 {* Menu item caption text (including '&' indicating mnemonic characters,
11242 and keyboard accelerator representation string, usually following
11243 tabulation character). }
11244 property Items[ Id: HMenu ]: PMenu read GetItems;
11245 {* Returns menu item object by its index or by menu id. Since menu id
11246 values are starting from 4096, values from 0 to 4095 are interpreted
11247 as absolute index of menu item. Be careful accessing menu items or
11248 submenus by index, if you dynamically insert or delete items or
11249 submenus. In this version, separators are enumerating too, like
11250 all other items. Use index -1 to access object itself. The first
11251 item of a menu (or the first subitem of submenu item) has index 0.
11252 Children are enumerating before all siblings. The maximum available
11253 index is (Count - 1), when accessing menu items by index. }
11254 property Count: Integer read GetCount;
11255 {* Count of items together with all its nested subitems. }
11256 function IndexOf( Item: PMenu ): Integer;
11257 {* Returns index of an item. This index can be used to access
11258 menu item. Value -2 is returned, if the Item is not a child for menu
11259 or menu item, and has no parents, which are children for it, etc.
11260 Menu object itself always has index -1. }
11261 property OnMenuItem : TOnMenuItem read FOnMenuItem write FOnMenuItem;
11262 {* Is called when menu item is clicked. Absolute index of menu item
11263 clicked is passed as the second parameter. TopParent always is
11264 passed as a Sender parameter. }
11265 property ByAccel: Boolean read fByAccel;
11266 {* True, when OnMenuItem is called not by mouse, but by accelerator key.
11267 Check this flag for entire menu (TopParent), not for item itself.
11268 (Note, that Sender in OnMenuItem always is TopParent menu object). )
11270 property IsSeparator: Boolean read FIsSeparator;
11271 {* TRUE, if a separator menu item. }
11272 property MenuBreak: TMenuBreak read FMenuBreak write SetMenuBreak;
11273 {* Menu item break type. }
11274 property OnUncheckRadioItem : TOnMenuItem read FOnRadioOff write FOnRadioOff;
11275 {* Is called when radio item becomes unchecked in menu in result of
11276 checking another radio item of the same radio group. }
11277 property RadioGroup: Integer read FRadioGroup write FRadioGroup;
11278 {* Radio group index. Several neighbour items with the same radio group
11279 index form radio group. Only single item from the same group can be
11280 checked at a time. }
11281 property IsCheckItem: Boolean read FIsCheckItem;
11282 {* If menu item is defined as check item, it is checked automatically
11283 when clicked. }
11284 procedure RadioCheckItem;
11285 {* Call this method to check radio item. (Calling this method for
11286 an item, which is not belonging to a radio group, just sets its
11287 Checked state to TRUE). }
11288 property Checked: Boolean index MFS_CHECKED read GetState write SetState;
11289 {* Checked state of the item. }
11290 property Enabled: Boolean
11291 {$IFDEF F_P}
11292 index $80000000 or MFS_DISABLED
11293 {$ELSE DELPHI}
11294 index Integer( $80000000 or MFS_DISABLED )
11295 {$ENDIF F_P/DELPHI}
11296 read GetState write SetState;
11297 {* Enabled state of the item. Whaen assigned, Grayed state also is
11298 set to arbitrary value (i.e., when Enabled is set to true, Grayed
11299 is set to FALSE. }
11300 property DefaultItem: Boolean index MFS_DEFAULT read GetState write SetState;
11301 {* Set this property to TRUE to make menu item default. Default item
11302 is drawn with bold.
11303 |<br>If you change DefaultItem at run-time and whant
11304 to provide changing its visual state, recreate the item first resetting
11305 Visible property, then setting it again. }
11306 property Highlight: Boolean index MFS_HILITE read GetState write SetState;
11307 {* Highlight state of the item. }
11308 property Visible: Boolean read FVisible write SetVisible;
11309 {* Visibility of menu item. }
11310 property Data: Pointer read FData write SetData;
11311 {* Data pointer, associated with the menu item. }
11312 property Bitmap: HBitmap read FBitmap write SetBitmap;
11313 {* Bitmap used for unchecked state of the menu item. }
11314 property BitmapChecked: HBitmap read FBmpChecked write SetBmpChecked;
11315 {* Bitmap used for checked state of the menu item. }
11316 property BitmapItem: HBitmap read FBmpItem write SetBmpItem;
11317 {* Bitmap used for item itself. In addition, following special values
11318 are possible:
11319 HBMMENU_CALLBACK, HBMMENU_MBAR_CLOSE, HBMMENU_MBAR_CLOSE_D,
11320 HBMMENU_MBAR_MINIMIZE, HBMMENU_MBAR_MINIMIZE_D, HBMMENU_MBAR_RESTORE,
11321 HBMMENU_POPUP_CLOSE, HBMMENU_POPUP_MAXIMIZE, HBMMENU_POPUP_MINIMIZE,
11322 HBMMENU_POPUP_RESTORE, HBMMENU_SYSTEM. }
11323 property Accelerator: TMenuAccelerator read FAccelerator write SetAccelerator;
11324 {* Accelerator for menu item. }
11325 property HelpContext: Integer read FHelpContext write SetHelpContext;
11326 {* Help context for entire menu (help context can not be assigned to
11327 individual menu items). }
11329 procedure AssignEvents( StartIdx: Integer; Events: array of TOnMenuItem );
11330 {* It is possible to assign its own event handler to every menu item
11331 using this call. This procedure also is called automatically in
11332 a constructor NewMenuEx. }
11334 procedure Popup( X, Y : Integer );
11335 {* Only for popup menu - to popup it at the given position on screen. }
11336 procedure PopupEx( X, Y: Integer );
11337 {* This version of popup command is very useful, when popup menu is activated
11338 when its parent window is not visible (e.g., for a kind of applications,
11339 which always are invisible, and can be activated only using tray icon).
11340 PopupEx method provides correct tracking of menu disappearing when mouse
11341 is clicked anywhere else on screen, fixing strange menu behavior in some
11342 Windows versions (NT).
11343 |<br>
11344 Actually, when PopupEx used, parent form is shown but below of visible
11345 screen, and when menu is disappearing, previous state of the form (visibility
11346 and position) are restored. If such solvation is not satisfying You,
11347 You can do something else (e.g., use region clipping, etc.) }
11348 property OnPopup: TOnEvent read fOnPopup write fOnPopup;
11349 {* This event occurs before the popup menu is shown. }
11350 property NotPopup: Boolean read FNotPopup write FNotPopup;
11351 {* Set this property to true to prevent popup of popup menu, e.g. in
11352 OnPopup event handler. }
11353 property Flags: DWORD read FPopupFlags write FPopupFlags;
11354 {* Pop-up flags, which are used to call TrackPopupMenuEx, when Popup or
11355 PopupEx method is called. Can be a combination of following values:
11356 |<br>
11357 TPM_CENTERALIGN or TPM_LEFTALIGN or TPM_RIGHTALIGN
11358 |<br>
11359 TPM_BOTTOMALIGN or TPM_TOPALIGN or TPM_VCENTERALIGN
11360 |<br>
11361 TPM_NONOTIFY or TPM_RETURNCMD
11362 |<br>
11363 TPM_LEFTBUTTON or TPM_RIGHTBUTTON
11364 |<br>
11365 TPM_HORNEGANIMATION or TPM_HORPOSANIMATION or TPM_NOANIMATION or
11366 TPM_VERNEGANIMATION or TPM_VERPOSANIMATION
11367 |<br>
11368 TPM_HORIZONTAL or TPM_VERTICAL.
11369 |<br>
11370 By default, a combination TPM_LEFTALIGN or TPM_LEFTBUTTON is used. }
11371 function Insert(InsertBefore: Integer; ACaption: PChar; Event: TOnMenuItem;
11372 Options: TMenuOptions): PMenu;
11373 {* Inserts new menu item before item, given by Id (>=4096) or index
11374 value InsertBefore. Pointer to an object created is returned. }
11375 property SubMenu: HMenu read FHandle; // write SetSubMenu;
11376 {* Submenu associated with the menu item. The same as Handle. It was possible
11377 in ealier versions to change this value, replacing (removing, assigning)
11378 entire popup menu as a submenu for menu item.
11379 But in modern version of TMenu, this is not possible.
11380 Instead, entire menu object should be added or removed using
11381 InsertSubmenu or RemoveSubmenu methods. }
11382 procedure InsertSubMenu( SubMenuToInsert: PMenu; InsertBefore: Integer );
11383 {* Inserts existing menu item (together with its subitems if any present)
11384 into given position. See also RemoveSubMenu. }
11385 function RemoveSubMenu( ItemToRemove: Integer ): PMenu;
11386 {* Removes menu item from the menu, returning TMenu object, representing it,
11387 if submenu item, having its own children, detached. If an individual menu
11388 item is removed, nil is returned.
11389 This function can be useful to add or remove dynamically entire submenus
11390 (created together with its subitems). }
11391 property OnMeasureItem: TOnMeasureItem read FOnMeasureItem write SetOnMeasureItem;
11392 {* This event is called for owner-drawn menu items. Event handler should return
11393 menu item height in lower word of a result and item width (for menu) in
11394 high word of result. If either for height or for width returned value is 0,
11395 a default one is used. }
11396 property OnDrawItem: TOnDrawItem read FOnDrawItem write SetOnDrawItem;
11397 {* This event is called for owner-drawn menu items. }
11398 property OwnerDraw: Boolean read FOwnerDraw write SetOwnerDraw;
11399 {* Set this property to true for some items to make it owner-draw. }
11401 // For compatibility with old code (be sure that item with given index
11402 // actually exists):
11403 function GetMenuItemHandle( Idx : Integer ): DWORD;
11404 {* Returns Id of menu item with given index. }
11405 property ItemHandle[ Idx: Integer ]: DWORD read GetMenuItemHandle;
11406 {* Returns handle for item given by index. }
11407 property ItemChecked[ Idx : Integer ] : Boolean read GetItemChecked write SetItemChecked;
11408 {* True, if correspondent menu item is checked. }
11409 procedure RadioCheck( Idx : Integer );
11410 {* Call this method to check radio item. For radio items, do not
11411 use assignment to ItemChecked or Checked properties. }
11412 property ItemBitmap[ Idx: Integer ]: HBitmap read GetItemBitmap write SetItemBitmap;
11413 {* This property allows to assign bitmap to menu item (for unchecked state
11414 only - for checked menu items default checkmark bitmap is used). }
11415 procedure AssignBitmaps( StartIdx: Integer; Bitmaps: array of HBitmap );
11416 {* Can be used to assign bitmaps to several menu items during one call. }
11417 property ItemText[ Idx: Integer ]: String read GetItemText write SetItemText;
11418 {* This property allows to get / modify menu item text at run time. }
11419 property ItemEnabled[ Idx: Integer ]: Boolean read GetItemEnabled write SetItemEnabled;
11420 {* Controls enabling / disabling menu items. Disabled menu items are
11421 displayed (grayed) but inaccessible to click. }
11422 property ItemVisible[ Idx: Integer ]: Boolean read GetItemVisible write SetItemVisible;
11423 {* This property allows to simulate visibility of menu items (implementing
11424 it by removing or inserting again if needed. For items of submenu, which
11425 is made invisible, True is returned. If such item made Visible, entire
11426 submenu with all its parent menu items becomes visible. To release menu
11427 properly it is necessary to make before all its items visible again.
11428 This does not matter, if menu is released at the end of execution, but
11429 can be sensible if owner form is destroyed and re-created at run time
11430 dynamically. }
11431 function ParentItem( Idx: Integer ): Integer;
11432 {* Returns index of parent menu item (for submenu item). If there are no
11433 such item (Idx corresponds to root level menu item), -1 is returned. }
11434 property ItemAccelerator[ Idx: Integer ]: TMenuAccelerator read GetItemAccelerator write SetItemAccelerator;
11435 {* Allows to get / change accelerator key kodes assigned to menu items.
11436 Has no effect unless SupportMnemonics called for a form. }
11437 property ItemSubmenu[ Idx: Integer ]: HMenu read GetItemSubmenu; // write SetItemSubmenu;
11438 {* Retrieves submenu item dynamically. See also SubMenu property. }
11440 // by Sergey Shisminzev:
11441 function AddItem(ACaption: PChar; Event: TOnMenuItem; Options: TMenuOptions): Integer;
11442 {* Adds menu item dynamically. Returns ID of the added item. }
11443 function InsertItem(InsertBefore: Integer; ACaption: PChar; Event: TOnMenuItem; Options: TMenuOptions): Integer;
11444 {* Inserts menu item before an item with ID, given by InsertBefore parameter. }
11445 function InsertItemEx(InsertBefore: Integer; ACaption: PChar; Event: TOnMenuItem; Options: TMenuOptions;
11446 ByPosition: Boolean): Integer;
11447 {* Inserts menu item by command or by position, dependant on ByPosition parameter }
11448 procedure RedrawFormMenuBar;
11449 {* }
11451 {$IFDEF USE_MENU_CURCTL}
11452 property CurCtl: PControl read fCurCtl;
11453 {* By Alexander Pravdin. This property is assigned to a control which were
11454 initiated a pop-up, for popup menu. }
11455 {$ENDIF USE_MENU_CURCTL}
11457 end;
11458 //[END OF TMenu DEFINITION]
11460 //[MenuStructSize VARIABLE]
11461 function MenuStructSize: Integer;
11462 {* Returns 44 under Windows95, and 48 (=sizeof(TMenuItemInfo) under all other
11463 Windows versions. }
11465 //[NewMenu DECLARATION]
11466 function NewMenu( AParent : PControl; MaxCmdReserve: DWORD; const Template : array of PChar;
11467 aOnMenuItem: TOnMenuItem ): PMenu;
11468 {* Menu constructor. First created menu becomes main menu of form (if AParent
11469 is a form). All other menus becomes popup (can be activated using Popup
11470 method). To provide dynamic replacing of main menu, create all popup
11471 menus as children of any other control, not form itself.
11472 When Menu is created, pass FirstCmd integer value to set it
11473 as ID of first menu item (all other ID's obtained by incrementing this value),
11474 and Template, which is an array of PChar (usually array of string constants),
11475 containing list of menu item identifiers and/or formatting characters.
11476 |<br>&nbsp;&nbsp;&nbsp;
11477 FirstCmd value is assigned to first menu item created as its ID,
11478 all follow menu items are assigned to ID's obtained from FirstCmd incrementing
11479 it by 1. It is desirable to provide not intersected ranges of ID's for
11480 defferent menus in the applet.
11481 |<br>&nbsp;&nbsp;&nbsp;
11482 Following formatting characters can be used in menu template strings:
11483 |&L=<br><b>%1</b>
11484 <L &amp; (in identifier)> - to underline next character and use it as a shortcut character
11485 when possible;
11486 <L + (in front of identifier)> - to make item checked. If also
11487 |<b>!</b> is used before <b>
11489 |</b> than radioitem is defined;
11490 <L - (in front of identifier)> - item not checked;
11491 <L - (separate)> - separator (between two items);
11492 <L ( (separate)> - start of submenu;
11493 <L ) (separate)> - end of submenu;
11494 |<br>&nbsp;&nbsp;&nbsp;
11495 To get access to menu items, use constants 0, 1, etc. It is a good idea
11496 to create special enumerated type to index correspondent menu items
11497 using Ord( ) operator. Note in that case, that it is necessary only to
11498 define constants correspondent to identifiers (positions, correspondent
11499 to separators or submenu brackets are not identified by numbers).
11500 |<br>&nbsp;&nbsp;&nbsp;
11503 function NewMenuEx( AParent : PControl; FirstCmd : Integer; const Template : array of PChar;
11504 aOnMenuItems: array of TOnMenuItem ): PMenu;
11505 {* Creates menu, assigning its own event handler for every (enough) menu item. }
11507 //[MakeAccelerator DECLARATION]
11508 function MakeAccelerator( fVirt: Byte; Key: Word ): TMenuAccelerator;
11509 {* Creates accelerator item to assign it to TMenu.ItemAccelerator[ ] property
11510 easy.}
11512 //[GetAcceleratorText DECLARATION]
11513 // {YS} added 7 Aug 2004
11514 function GetAcceleratorText( const Accelerator: TMenuAccelerator ): string;
11515 {* Returns text representation of accelerator. }
11517 // NewActionList, TAction - by Yury Sidorov
11518 //[ACTIONS OBJECT]
11519 { ----------------------------------------------------------------------
11521 TAction and TActionList
11523 ----------------------------------------------------------------------- }
11524 type
11525 PControlRec = ^TControlRec;
11526 TOnUpdateCtrlEvent = procedure(Sender: PControlRec) of object;
11528 TCtrlKind = (ckControl, ckMenu, ckToolbar);
11529 TControlRec = record
11530 Ctrl: PObj;
11531 CtrlKind: TCtrlKind;
11532 ItemID: integer;
11533 UpdateProc: TOnUpdateCtrlEvent;
11534 end;
11536 {++}(* TAction = class;*){--}
11537 PAction = {-}^{+}TAction;
11539 {++}(* TActionList = class;*){--}
11540 PActionList = {-}^{+}TActionList;
11542 //[TAction DEFINITION]
11543 TAction = {-} object( TObj ) {+}{++}(*class*){--}
11544 {*! Use action objects, in conjunction with action lists, to centralize the response
11545 to user commands (actions).
11546 Use AddControl, AddMenuItem, AddToolbarButton methods to link controls to an action.
11547 See also TActionList.
11549 protected
11550 FControls: PList;
11551 FCaption: string;
11552 FChecked: boolean;
11553 FVisible: boolean;
11554 FEnabled: boolean;
11555 FHelpContext: integer;
11556 FHint: string;
11557 FOnExecute: TOnEvent;
11558 FAccelerator: TMenuAccelerator;
11559 FShortCut: string;
11560 procedure DoOnMenuItem(Sender: PMenu; Item: Integer);
11561 procedure DoOnToolbarButtonClick(Sender: PControl; BtnID: Integer);
11562 procedure DoOnControlClick(Sender: PObj);
11564 procedure SetCaption(const Value: string);
11565 procedure SetChecked(const Value: boolean);
11566 procedure SetEnabled(const Value: boolean);
11567 procedure SetHelpContext(const Value: integer);
11568 procedure SetHint(const Value: string);
11569 procedure SetVisible(const Value: boolean);
11570 procedure SetAccelerator(const Value: TMenuAccelerator);
11571 procedure UpdateControls;
11573 procedure LinkCtrl(ACtrl: PObj; ACtrlKind: TCtrlKind; AItemID: integer; AUpdateProc: TOnUpdateCtrlEvent);
11574 procedure SetOnExecute(const Value: TOnEvent);
11576 procedure UpdateCtrl(Sender: PControlRec);
11577 procedure UpdateMenu(Sender: PControlRec);
11578 procedure UpdateToolbar(Sender: PControlRec);
11580 public
11581 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
11582 procedure LinkControl(Ctrl: PControl);
11583 {* Add a link to a TControl or descendant control. }
11584 procedure LinkMenuItem(Menu: PMenu; MenuItemIdx: integer);
11585 {* Add a link to a menu item. }
11586 procedure LinkToolbarButton(Toolbar: PControl; ButtonIdx: integer);
11587 {* Add a link to a toolbar button. }
11588 procedure Execute;
11589 {* Executes a OnExecute event handler. }
11590 property Caption: string read FCaption write SetCaption;
11591 {* Text caption. }
11592 property Hint: string read FHint write SetHint;
11593 {* Hint (tooltip). Currently used for toolbar buttons only. }
11594 property Checked: boolean read FChecked write SetChecked;
11595 {* Checked state. }
11596 property Enabled: boolean read FEnabled write SetEnabled;
11597 {* Enabled state. }
11598 property Visible: boolean read FVisible write SetVisible;
11599 {* Visible state. }
11600 property HelpContext: integer read FHelpContext write SetHelpContext;
11601 {* Help context. }
11602 property Accelerator: TMenuAccelerator read FAccelerator write SetAccelerator;
11603 {* Accelerator for menu items. }
11604 property OnExecute: TOnEvent read FOnExecute write SetOnExecute;
11605 {* This event is executed when user clicks on a linked object or Execute method was called. }
11606 end;
11607 //[END OF TAction DEFINITION]
11609 //[TActionList DEFINITION]
11610 TActionList = {-} object( TObj ) {+}{++}(*class*){--}
11611 {*! TActionList maintains a list of actions used with components and controls,
11612 such as menu items and buttons.
11613 Action lists are used, in conjunction with actions, to centralize the response
11614 to user commands (actions).
11615 Write an OnUpdateActions handler to update actions state.
11616 Created using function NewActionList.
11617 See also TAction.
11619 protected
11620 FOwner: PControl;
11621 FActions: PList;
11622 FOnUpdateActions: TOnEvent;
11623 function GetActions(Idx: integer): PAction;
11624 function GetCount: integer;
11625 protected
11626 procedure DoUpdateActions(Sender: PObj);
11627 public
11628 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
11629 function Add(const ACaption, AHint: string; OnExecute: TOnEvent): PAction;
11630 {* Add a new action to the list. Returns pointer to action object. }
11631 procedure Delete(Idx: integer);
11632 {* Delete action by index from list. }
11633 procedure Clear;
11634 {* Clear all actions in the list. }
11635 property Actions[Idx: integer]: PAction read GetActions;
11636 {* Access to actions in the list. }
11637 property Count: integer read GetCount;
11638 {* Number of actions in the list.. }
11639 property OnUpdateActions: TOnEvent read FOnUpdateActions write FOnUpdateActions;
11640 {* Event handler to update actions state. This event is called each time when application
11641 goes in the idle state (no messages in the queue). }
11642 end;
11643 //[END OF TActionList DEFINITION]
11645 //[NewActionList DECLARATION]
11646 function NewActionList(AOwner: PControl): PActionList;
11647 {* Action list constructor. AOwner - owner form.
11648 |<hr>
11657 <R System functions and working with windows>
11659 //[Window FUNCTIONS DECLARATIONS]
11660 type
11661 TWindowChildKind = ( wcActive, wcFocus, wcCapture, wcMenuOwner,
11662 wcMoveSize, wcCaret );
11663 {* Type of window child kind. Used in function GetWindowChild. }
11665 function GetWindowChild( Wnd: HWnd; Kind: TWindowChildKind ): HWnd;
11666 {* Returns child of given top-level window, having given characteristics.
11667 For example, it is possible to get know for foreground window,
11668 which of its child window has focus. This function does not work in old
11669 Windows 95 (returns Wnd in that case). But for Windows 98, Windows NT/2000
11670 this function works fine. To obtain focused child of the window,
11671 use GetFocusedWindow, which is independant from Windows version. }
11673 function GetFocusedChild( Wnd: HWnd ): HWnd;
11674 {* Returns focused child of given window (which should be foreground
11675 and active, certainly). 0 is returned either if Wnd is not active
11676 or Wnd has no focused child window. }
11678 function Stroke2Window( Wnd: HWnd; const S: String ): Boolean;
11679 {* Posts characters from string S to those child window of Wnd, which
11680 has focus now (top-level window Wnd must be foreground, and have
11681 focused edit-aware control to receive the stroke).
11682 |<br>
11683 This function allows only to post typeable characters (including
11684 such special symbols as #13 (Enter), #9 (Tab), #8 (BackSpace), etc.
11685 |<br>
11686 See also function Stroke2WindowEx, which allows to post any key down
11687 and up events, simulating keyboard for given (automated) application. }
11689 function Stroke2WindowEx( Wnd: HWnd; const S: String; Wait: Boolean ): Boolean;
11690 {* In addition to function Stroke2Window, this one can send special keys
11691 to given window, including functional keys and navigation keys. To
11692 post special key to target window, place a combination of names of
11693 such key together with keys, which should be passed simultaneously,
11694 between square or figure brackets. For example, [Ctrl F1], [Alt Shift Home],
11695 [Ctrl E]. For letters and usual characters, it is not necessary to
11696 simulate pressing it with determining all Shift combinations and it is
11697 sufficient to pass characters as is. (E.g., not '[Shift 1]', but '!'). }
11699 function FindWindowByThreadID( ThreadID : DWORD ) : HWnd;
11700 {* Searches for window, belonging to a given thread. }
11702 function GetDesktopRect : TRect;
11703 {* Returns rectangle of screen, free of taskbar and other
11704 similar app-bars, which reduces size of available desktop
11705 when created. }
11706 function GetWorkArea: TRect;
11707 {* The same as GetDesktopRect, but obtained calling SystemParametersInfo. }
11709 function ExecuteWait( const AppPath, CmdLine, DfltDirectory: String;
11710 Show: DWORD; TimeOut: DWORD; ProcID: PDWORD ): Boolean;
11711 {* Allows to execute an application and wait when it is finished. Pass
11712 INFINITE constant as TimeOut, if You sure that application is finished
11713 anyway. If another value passed as a TimeOut (in milliseconds), and
11714 application was not finished for that time, ExecuteWait is returning
11715 FALSE, and if ProcID is not nil, than ProcID^ contains started process
11716 handle (it can be used to wait it more, or to terminate it using
11717 TerminateProcess API function).
11718 |<br>
11719 Launching application can be console or GUI - it does not matter.
11720 Pass SW_SHOW, SW_HIDE or other SW_XXX constant as Show parameter
11721 as appropriate.
11722 |<br>
11723 Trie is returned only in case when application specified was launched
11724 successfully and finished for TimeOut specified. Otherwise, check
11725 ProcID^ variable: if it is 0, process could not be launched (and it
11726 is possible to get information about error using GetLastError API
11727 function in a such case). You can freely pass nil in place of ProcID
11728 parameter, but this is acually correct only when TimeOut is INFINITE. }
11729 function ExecuteIORedirect( const AppPath, CmdLine, DfltDirectory: String;
11730 Show: DWORD; ProcID: PDWORD; InPipe, OutPipeWr, OutPipeRd: PHandle ): Boolean;
11731 {* Executes an application with its console input and output redirection.
11732 Terminating of the application is not waiting, but if ProcID pointer
11733 is defined, it receives process Id launched, so it is possible to
11734 call WaitForSingleObject for it. InPipe is a pointer to THandle variable
11735 which receives a handle to input pipe of the console redirected. The same
11736 is for OutPipeWr and OutPipeRd, but for output of the console redirected.
11737 Before reading from OutPipeRd^, first close OutPipeWr^. If you run
11738 simple console application, for which you want to read results after its
11739 termination, you can use ExecuteConsoleAppIORedirect instead.
11740 |<br>&nbsp;&nbsp;&nbsp;
11741 Notes: if your application is not console and it does not create console
11742 using AllocConsole, this function will fail to redirect input-output. }
11743 function ExecuteConsoleAppIORedirect( const AppPath, CmdLine, DfltDirectory: String;
11744 Show: DWORD; const InStr: String; var OutStr: String; WaitTimeout: DWORD )
11745 : Boolean;
11746 {* Executes an application, redirecting its console input and output.
11747 After redirecting input and output and launching the application,
11748 content of InStr is written to input stream of the application, then
11749 the application is waiting for its termination (WaitTimeout milliseconds
11750 or INFINITE, as passed) and console output of the application is read to
11751 OutStr. TRUE is returned only in case, when all these tasks are
11752 completed successfully.
11753 |<br>&nbsp;&nbsp;&nbsp;
11754 Notes: if your application is not console and it does not create console
11755 using AllocConsole, this function will fail to redirect input-output. }
11758 function WindowsShutdown( const Machine : String; Force, Reboot : Boolean ) : Boolean;
11759 {* Shut down of Windows NT. Pass Machine = '' to shutdown this PC.
11760 Pass Reboot = True to reboot immediatelly after shut down. }
11762 type
11763 TWindowsVersion = ( wv31, wv95, wv98, wvNT, wvY2K, wvXP, wvLongHorn );
11764 {* Windows versions constants. }
11765 TWindowsVersions = Set of TWindowsVersion;
11766 {* Set of Windows version (e.g. to define a range of versions supported by the
11767 application). }
11769 function WinVer : TWindowsVersion;
11770 {* Returns Windows version. }
11771 function IsWinVer( Ver : TWindowsVersions ) : Boolean;
11772 {* Returns True if Windows version is in given range of values. }
11774 //[Parameters FUNCTIONS DECLARATIONS]
11775 function ParamStr( Idx: Integer ): String;
11776 {* Returns command-line parameter by index. This function supersides
11777 standard ParamStr function. }
11778 function ParamCount: Integer;
11779 {* Returns number of parameters in command line.
11780 |<hr>
11784 //{$DEFINE CHK_BITBLT}
11785 procedure Chk_BitBlt;
11786 {$IFDEF ASM_VERSION}
11787 procedure StartDC;
11788 procedure FinishDC;
11789 {$ENDIF ASM_VERSION}
11791 //[WndProcXXX OTHER DECLARATIONS]
11792 function WndProcCtrl( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
11793 function WndProcDoEraseBkgnd( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
11795 var CreatingWindow: PControl;
11796 //ActiveWindow: HWnd;
11798 //[Assert OPERATOR DECLARATION]
11800 {$IFDEF _D2}
11801 // Assert operator was not available in Delphi2. Provide here easy Assert
11802 // procedure for Delphi2.
11803 procedure Assert( Cond: Boolean; const Msg: String );
11805 var AssertErrorProc: procedure( const Message, Filename: AnsiString; LineNumber: Integer );
11806 {$ENDIF}
11810 //[CUSTOM EXTENSIONS]
11811 {$IFDEF USE_CUSTOMEXTENSIONS}
11812 {$I CUSTOM_KOL_EXTENSION.inc} // See comments in TControl
11813 {$ENDIF}
11816 {$IFDEF DEBUG_ENDSESSION}
11817 var EndSession_Initiated: Boolean;
11818 {$ENDIF}
11820 //[FMMNotify VARIABLE]
11822 FMMNotify: procedure( var Msg: TMsg );
11824 //[procedure ClearText forward declaration]
11825 procedure ClearText( Sender: PControl );
11826 //[procedure ClearListbox forward declaration]
11827 procedure ClearListbox( Sender: PControl );
11828 //[procedure ClearCombobox forward declaration]
11829 procedure ClearCombobox( Sender: PControl );
11830 //[procedure ClearListView forward declaration]
11831 procedure ClearListView( Sender: PControl );
11832 //[procedure ClearTreeView forward declaration]
11833 procedure ClearTreeView( TV: PControl );
11835 //[START OF ACTIONS]
11836 const
11837 ButtonActions: TCommandActions = (
11838 aClear: ClearText;
11839 aAddText: nil;
11840 aClick: BN_CLICKED;
11841 aEnter: BN_SETFOCUS;
11842 aLeave: BN_KILLFOCUS;
11843 aChange: 0; //BN_CLICKED;
11844 aSelChange: 0;
11845 aGetCount: 0;
11846 aSetCount: 0;
11847 aGetItemLength: 0;
11848 aGetItemText: 0;
11849 aSetItemText: 0;
11850 aGetItemData: 0;
11851 aSetItemData: 0;
11852 aAddItem: 0;
11853 aDeleteItem: 0;
11854 aInsertItem: 0;
11855 aFindItem: 0;
11856 aFindPartial: 0;
11857 aItem2Pos: 0;
11858 aPos2Item: 0;
11859 aGetSelCount: 0;
11860 aGetSelected: 0;
11861 aGetSelRange: 0;
11862 aExGetSelRange: 0;
11863 aGetCurrent: 0;
11864 aSetSelected: 0;
11865 aSetCurrent: 0;
11866 aSetSelRange: 0;
11867 aExSetSelRange: 0;
11868 aGetSelection: 0;
11869 aReplaceSel: 0;
11870 aTextAlignLeft: BS_LEFT;
11871 aTextAlignRight: BS_RIGHT;
11872 aTextAlignCenter: BS_CENTER;
11873 aTextAlignMask: 0;
11874 aVertAlignCenter: BS_VCENTER shr 8;
11875 aVertAlignTop: BS_TOP shr 8;
11876 aVertAlignBottom: BS_BOTTOM shr 8;
11877 aDir: 0;
11878 aSetLimit: 0;
11879 aSetImgList: 0;
11880 aAutoSzX: 14;
11881 aAutoSzY: 0;
11882 aSetBkColor: 0;
11885 const
11886 LabelActions: TCommandActions = (
11887 aClear: ClearText;
11888 aAddText: nil;
11889 aClick: 0;
11890 aEnter: 0;
11891 aLeave: 0;
11892 aChange: 0;
11893 aSelChange: 0;
11894 aGetCount: 0;
11895 aSetCount: 0;
11896 aGetItemLength: 0;
11897 aGetItemText: 0;
11898 aSetItemText: 0;
11899 aGetItemData: 0;
11900 aSetItemData: 0;
11901 aAddItem: 0;
11902 aDeleteItem: 0;
11903 aInsertItem: 0;
11904 aFindItem: 0;
11905 aFindPartial: 0;
11906 aItem2Pos: 0;
11907 aPos2Item: 0;
11908 aGetSelCount: 0;
11909 aGetSelected: 0;
11910 aGetSelRange: 0;
11911 aExGetSelRange: 0;
11912 aGetCurrent: 0;
11913 aSetSelected: 0;
11914 aSetCurrent: 0;
11915 aSetSelRange: 0;
11916 aExSetSelRange: 0;
11917 aGetSelection: 0;
11918 aReplaceSel: 0;
11919 aTextAlignLeft: SS_LEFT;
11920 aTextAlignRight: SS_RIGHT;
11921 aTextAlignCenter: SS_CENTER;
11922 aTextAlignMask: SS_LEFTNOWORDWRAP;
11923 aVertAlignCenter: SS_CENTERIMAGE shr 8;
11924 aVertAlignTop: 0;
11925 aVertAlignBottom: 0;
11926 aDir: 0;
11927 aSetLimit: 0;
11928 aSetImgList: 0;
11929 aAutoSzX: 1;
11930 aAutoSzY: 1;
11931 aSetBkColor: 0;
11934 const
11935 EN_LINK = $070b;
11936 EditActions: TCommandActions = (
11937 aClear: ClearText;
11938 aAddText: nil;
11939 aClick: 0;
11940 aEnter: EN_SETFOCUS;
11941 aLeave: EN_KILLFOCUS;
11942 aChange: EN_CHANGE;
11943 aSelChange: 0;
11944 aGetCount: EM_GETLINECOUNT;
11945 aSetCount: 0;
11946 aGetItemLength: EM_LINELENGTH;
11947 aGetItemText: EM_GETLINE;
11948 aSetItemText: EM_REPLACESEL;
11949 aGetItemData: 0;
11950 aSetItemData: 0;
11951 aAddItem: 0;
11952 aDeleteItem: 0;
11953 aInsertItem: 0;
11954 aFindItem: 0;
11955 aFindPartial: 0;
11956 aItem2Pos: EM_LINEINDEX;
11957 aPos2Item: EM_LINEFROMCHAR;
11958 aGetSelCount: EM_GETSEL;
11959 aGetSelected: 0;
11960 aGetSelRange: EM_GETSEL;
11961 aExGetSelRange: 0;
11962 aGetCurrent: EM_LINEINDEX;
11963 aSetSelected: 0;
11964 aSetCurrent: 0;
11965 aSetSelRange: EM_SETSEL;
11966 aExSetSelRange: 0;
11967 aGetSelection: 0;
11968 aReplaceSel: EM_REPLACESEL;
11969 aTextAlignLeft: ES_LEFT;
11970 aTextAlignRight: ES_RIGHT;
11971 aTextAlignCenter: ES_CENTER;
11972 aTextAlignMask: 0;
11973 aVertAlignCenter: 0;
11974 aVertAlignTop: 0;
11975 aVertAlignBottom: 0;
11976 aDir: 0;
11977 aSetLimit: EM_SETLIMITTEXT;
11978 aSetImgList: 0;
11979 aAutoSzX: 0;
11980 aAutoSzY: 6;
11981 aSetBkColor: 0;
11982 aItem2XY: EM_POSFROMCHAR;
11985 const
11986 ListActions: TCommandActions = (
11987 aClear: ClearListbox;
11988 aAddText: nil;
11989 aClick: LBN_DBLCLK;
11990 aEnter: LBN_SETFOCUS;
11991 aLeave: LBN_KILLFOCUS;
11992 aChange: 0;
11993 aSelChange: LBN_SELCHANGE;
11994 aGetCount: LB_GETCOUNT;
11995 aSetCount: LB_SETCOUNT;
11996 aGetItemLength: LB_GETTEXTLEN;
11997 aGetItemText: LB_GETTEXT;
11998 aSetItemText: 0;
11999 aGetItemData: LB_GETITEMDATA;
12000 aSetItemData: LB_SETITEMDATA;
12001 aAddItem: LB_ADDSTRING;
12002 aDeleteItem: LB_DELETESTRING;
12003 aInsertItem: LB_INSERTSTRING;
12004 aFindItem: LB_FINDSTRINGEXACT;
12005 aFindPartial: LB_FINDSTRING;
12006 aItem2Pos: 0;
12007 aPos2Item: 0;
12008 aGetSelCount: LB_GETSELCOUNT;
12009 aGetSelected: LB_GETSEL;
12010 aGetSelRange: 0;
12011 aExGetSelRange: 0;
12012 aGetCurrent: LB_GETCURSEL;
12013 aSetSelected: LB_SETSEL;
12014 aSetCurrent: LB_SETCURSEL;
12015 aSetSelRange: 0;
12016 aExSetSelRange: 0;
12017 aGetSelection: 0;
12018 aReplaceSel: 0;
12019 aTextAlignLeft: 0;
12020 aTextAlignRight: 0;
12021 aTextAlignCenter: 0;
12022 aTextAlignMask: 0;
12023 aVertAlignCenter: 0;
12024 aVertAlignTop: 0;
12025 aVertAlignBottom: 0;
12026 aDir: LB_DIR;
12027 aSetLimit: 0;
12028 aSetImgList: 0;
12029 aAutoSzX: 0;
12030 aAutoSzY: 0;
12031 aSetBkColor: 0;
12032 aItem2XY: LB_GETITEMRECT;
12035 const
12036 ComboActions: TCommandActions = (
12037 aClear: ClearCombobox;
12038 aAddText: nil;
12039 aClick: CBN_DBLCLK;
12040 aEnter: CBN_SETFOCUS;
12041 aLeave: CBN_KILLFOCUS;
12042 aChange: CBN_EDITCHANGE;
12043 aSelChange: CM_CBN_SELCHANGE; // CBN_SELCHANGE;
12044 aGetCount: CB_GETCOUNT;
12045 aSetCount: 0;
12046 aGetItemLength: CB_GETLBTEXTLEN;
12047 aGetItemText: CB_GETLBTEXT;
12048 aSetItemText: 0;
12049 aGetItemData: CB_GETITEMDATA;
12050 aSetItemData: CB_SETITEMDATA;
12051 aAddItem: CB_ADDSTRING;
12052 aDeleteItem: CB_DELETESTRING;
12053 aInsertItem: CB_INSERTSTRING;
12054 aFindItem: CB_FINDSTRINGEXACT;
12055 aFindPartial: CB_FINDSTRING;
12056 aItem2Pos: 0;
12057 aPos2Item: 0;
12058 aGetSelCount: 0;
12059 aGetSelected: CB_GETCURSEL;
12060 aGetSelRange: 0;
12061 aExGetSelRange: 0;
12062 aGetCurrent: CB_GETCURSEL;
12063 aSetSelected: 0;
12064 aSetCurrent: CB_SETCURSEL;
12065 aSetSelRange: 0;
12066 aExSetSelRange: 0;
12067 aGetSelection: 0;
12068 aReplaceSel: 0;
12069 aTextAlignLeft: 0; //ES_LEFT;
12070 aTextAlignRight: 0; //ES_RIGHT;
12071 aTextAlignCenter: 0; //ES_CENTER;
12072 aTextAlignMask: 0;
12073 aVertAlignCenter: 0;
12074 aVertAlignTop: 0;
12075 aVertAlignBottom: 0;
12076 aDir: CB_DIR;
12077 aSetLimit: 0;
12078 aSetImgList: 0;
12079 aAutoSzX: 0;
12080 aAutoSzY: 6;
12081 aSetBkColor: 0;
12084 const
12085 ListViewActions: TCommandActions = (
12086 aClear: ClearListView;
12087 aAddText: nil;
12088 aClick: 0;
12089 aEnter: 0;
12090 aLeave: 0;
12091 aChange: LVN_ITEMCHANGED;
12092 aSelChange: 0;
12093 aGetCount: LVM_GETITEMCOUNT;
12094 aSetCount: LVM_SETITEMCOUNT;
12095 aGetItemLength: 0;
12096 aGetItemText: 0;
12097 aSetItemText: 0;
12098 aGetItemData: 0;
12099 aSetItemData: 0;
12100 aAddItem: 0;
12101 aDeleteItem: 0;
12102 aInsertItem: 0;
12103 aFindItem: 0;
12104 aFindPartial: 0;
12105 aItem2Pos: 0;
12106 aPos2Item: 0;
12107 aGetSelCount: $8000 or LVM_GETSELECTEDCOUNT;
12108 aGetSelected: 0;
12109 aGetSelRange: 0;
12110 aExGetSelRange: 0;
12111 aGetCurrent: LVM_GETNEXTITEM;
12112 aSetSelected: 0;
12113 aSetCurrent: 0;
12114 aSetSelRange: 0;
12115 aExSetSelRange: 0;
12116 aGetSelection: 0;
12117 aReplaceSel: 0;
12118 aTextAlignLeft: 0;
12119 aTextAlignRight: 0;
12120 aTextAlignCenter: 0;
12121 aTextAlignMask: 0;
12122 aVertAlignCenter: 0;
12123 aVertAlignTop: 0;
12124 aVertAlignBottom: 0;
12125 aDir: 0;
12126 aSetLimit: 0;
12127 aSetImgList: LVM_SETIMAGELIST;
12128 aAutoSzX: 0;
12129 aAutoSzY: 0;
12130 aSetBkColor: LVM_SETBKCOLOR;
12131 aItem2XY: LVM_GETITEMRECT;
12134 const
12135 TreeViewActions: TCommandActions = (
12136 aClear: ClearTreeView;
12137 aAddText: nil;
12138 aClick: 0;
12139 aEnter: 0;
12140 aLeave: 0;
12141 aChange: TVN_ENDLABELEDIT;
12142 aSelChange: TVN_SELCHANGED;
12143 aGetCount: TVM_GETCOUNT;
12144 aSetCount: 0;
12145 aGetItemLength: 0;
12146 aGetItemText: 0;
12147 aSetItemText: 0;
12148 aGetItemData: 0;
12149 aSetItemData: 0;
12150 aAddItem: 0;
12151 aDeleteItem: 0;
12152 aInsertItem: 0;
12153 aFindItem: 0;
12154 aFindPartial: 0;
12155 aItem2Pos: 0;
12156 aPos2Item: 0;
12157 aGetSelCount: 0;
12158 aGetSelected: 0;
12159 aGetSelRange: 0;
12160 aExGetSelRange: 0;
12161 aGetCurrent: 0;
12162 aSetSelected: 0;
12163 aSetCurrent: 0;
12164 aSetSelRange: 0;
12165 aExSetSelRange: 0;
12166 aGetSelection: 0;
12167 aReplaceSel: 0;
12168 aTextAlignLeft: 0;
12169 aTextAlignRight: 0;
12170 aTextAlignCenter: 0;
12171 aTextAlignMask: 0;
12172 aVertAlignCenter: 0;
12173 aVertAlignTop: 0;
12174 aVertAlignBottom: 0;
12175 aDir: CB_DIR;
12176 aSetLimit: 0;
12177 aSetImgList: TVM_SETIMAGELIST;
12178 aAutoSzX: 0;
12179 aAutoSzY: 0;
12180 aSetBkColor: TVM_SETBKCOLOR;
12181 aItem2XY: TVM_GETITEMRECT;
12184 const
12185 TabControlActions: TCommandActions = (
12186 aClear: ClearText;
12187 aAddText: nil;
12188 aClick: 0;
12189 aEnter: 0;
12190 aLeave: 0;
12191 aChange: TCN_SELCHANGE;
12192 aSelChange: TCN_SELCHANGE;
12193 aGetCount: TCM_GETITEMCOUNT;
12194 aSetCount: 0;
12195 aGetItemLength: 0;
12196 aGetItemText: 0;
12197 aSetItemText: 0;
12198 aGetItemData: 0;
12199 aSetItemData: 0;
12200 aAddItem: 0;
12201 aDeleteItem: 0;
12202 aInsertItem: 0;
12203 aFindItem: 0;
12204 aFindPartial: 0;
12205 aItem2Pos: 0;
12206 aPos2Item: 0;
12207 aGetSelCount: 0;
12208 aGetSelected: 0;
12209 aGetSelRange: 0;
12210 aExGetSelRange: 0;
12211 aGetCurrent: TCM_GETCURSEL;
12212 aSetSelected: 0;
12213 aSetCurrent: TCM_SETCURSEL; //TCM_SETCURFOCUS;
12214 aSetSelRange: 0;
12215 aExSetSelRange: 0;
12216 aGetSelection: 0;
12217 aReplaceSel: 0;
12218 aTextAlignLeft: 0;
12219 aTextAlignRight: 0;
12220 aTextAlignCenter: 0;
12221 aTextAlignMask: 0;
12222 aVertAlignCenter: 0;
12223 aVertAlignTop: 0;
12224 aVertAlignBottom: 0;
12225 aDir: CB_DIR;
12226 aSetLimit: 0;
12227 aSetImgList: TCM_SETIMAGELIST;
12228 aAutoSzX: 0;
12229 aAutoSzY: 0;
12230 aSetBkColor: 0;
12231 aItem2XY: TCM_GETITEMRECT;
12234 const
12235 RichEditActions: TCommandActions = (
12236 aClear: ClearText;
12237 aAddText: nil;
12238 aClick: 0;
12239 aEnter: EN_SETFOCUS;
12240 aLeave: EN_KILLFOCUS;
12241 aChange: EN_CHANGE;
12242 aSelChange: EN_SELCHANGE;
12243 aGetCount: EM_GETLINECOUNT;
12244 aSetCount: 0;
12245 aGetItemLength: EM_LINELENGTH;
12246 aGetItemText: EM_GETLINE;
12247 aSetItemText: EM_REPLACESEL;
12248 aGetItemData: 0;
12249 aSetItemData: 0;
12250 aAddItem: 0;
12251 aDeleteItem: 0;
12252 aInsertItem: 0;
12253 aFindItem: 0;
12254 aFindPartial: 0;
12255 aItem2Pos: EM_LINEINDEX;
12256 aPos2Item: EM_LINEFROMCHAR;
12257 aGetSelCount: 0; //EM_EXGETSEL;
12258 aGetSelected: 0;
12259 aGetSelRange: 0;
12260 aExGetSelRange: EM_EXGETSEL;
12261 aGetCurrent: EM_LINEINDEX;
12262 aSetSelected: 0;
12263 aSetCurrent: 0;
12264 aSetSelRange: 0;
12265 aExSetSelRange: EM_EXSETSEL;
12266 aGetSelection: EM_GETSELTEXT;
12267 aReplaceSel: EM_REPLACESEL;
12268 aTextAlignLeft: ES_LEFT;
12269 aTextAlignRight: ES_RIGHT;
12270 aTextAlignCenter: ES_CENTER;
12271 aTextAlignMask: 0;
12272 aVertAlignCenter: 0;
12273 aVertAlignTop: 0;
12274 aVertAlignBottom: 0;
12275 aDir: 0;
12276 aSetLimit: EM_EXLIMITTEXT;
12277 aSetImgList: 0;
12278 aAutoSzX: 0;
12279 aAutoSzY: 0;
12280 aSetBkColor: EM_SETBKGNDCOLOR;
12281 aItem2XY: EM_POSFROMCHAR;
12284 //[IMPLEMENTATION]
12285 implementation
12287 //[USES-2]
12288 uses
12289 ShellAPI,
12290 commdlg
12291 ; //, commctrl;
12292 // in Delphi3, including of commctrl.pas increases executable
12293 // onto about 30K. So, all needed definitions are copied here
12294 // (see commctrl.inc).
12295 //[END OF USES-2]
12297 {$IFDEF _D2orD3}
12298 const
12299 OFN_ENABLESIZING = $00800000;
12300 {$ENDIF}
12302 //[procedure Chk_BitBlt_ShowError]
12303 procedure Chk_BitBlt_ShowError;
12304 var Rslt: Integer;
12305 begin
12306 Rslt := GetLastError;
12307 ShowMessage( 'BitBlt ERROR: ' + Int2Str( Rslt )
12308 + ' ' + SysErrorMessage( Rslt ) );
12309 end;
12310 //[ENDe Chk_BitBlt_ShowError]
12312 //[procedure Chk_BitBlt]
12313 procedure Chk_BitBlt;
12314 var Rslt: Integer;
12315 begin
12317 MOV Rslt, EAX
12318 end;
12319 if Rslt = 0 then
12320 begin
12321 Chk_BitBlt_ShowError;
12323 int 3;
12324 end;
12325 end;
12326 end;
12327 //[ENDe Chk_BitBlt]
12329 //[FUNCTION MulDiv]
12330 {$IFNDEF FPC}
12331 function MulDiv( A, B, C: Integer ): Integer;
12333 IMUL EDX
12334 IDIV ECX
12335 end;
12336 {$ENDIF}
12337 //[END MulDiv]
12340 {$ifdef _D2}
12342 //[PROCEDURE Assert]
12343 procedure Assert( Cond: Boolean; const Msg: String );
12344 begin
12345 if not Cond then
12346 begin
12347 AssertErrorProc( Msg, '', 0 );
12348 //MsgOK( Msg );
12350 int 3;
12351 end;
12352 end;
12353 end;
12355 //[API CreateDIBSection]
12356 function CreateDIBSection(DC: HDC; const p2: TBitmapInfo; p3: UINT;
12357 var p4: Pointer; p5: THandle; p6: DWORD): HBITMAP; stdcall;
12358 external gdi32 name 'CreateDIBSection';
12361 //[PROCEDURE _LStrFromPCharLen]
12362 procedure _LStrFromPCharLen(var Dest: AnsiString; Source: PAnsiChar; Length: Integer);
12364 { -> EAX pointer to dest }
12365 { EDX source }
12366 { ECX length }
12368 PUSH EBX
12369 PUSH ESI
12370 PUSH EDI
12372 MOV EBX,EAX
12373 MOV ESI,EDX
12374 MOV EDI,ECX
12376 { allocate new string }
12378 MOV EAX,EDI
12380 CALL System.@NewAnsiString
12381 MOV ECX,EDI
12382 MOV EDI,EAX
12384 TEST ESI,ESI
12385 JE @@noMove
12387 MOV EDX,EAX
12388 MOV EAX,ESI
12389 CALL Move
12391 { assign the result to dest }
12393 @@noMove:
12394 MOV EAX,EBX
12395 CALL System.@LStrClr
12396 MOV [EBX],EDI
12398 POP EDI
12399 POP ESI
12400 POP EBX
12401 end;
12402 {$endif}
12405 //[API InitCommonControls]
12406 procedure InitCommonControls; external cctrl name 'InitCommonControls';
12408 type
12409 TInitCommonControlsEx = packed record
12410 dwSize: DWORD;
12411 dwICC: DWORD;
12412 end;
12413 PInitCommonControlsEx = ^TInitCommonControlsEx;
12415 var ComCtl32_Module: HModule;
12416 //[procedure DoInitCommonControls]
12417 procedure DoInitCommonControls( dwICC: DWORD );
12418 var Proc: procedure( ICC: PInitCommonControlsEx ); stdcall;
12419 ICC: TInitCommonControlsEx;
12420 begin
12421 InitCommonControls;
12422 if ComCtl32_Module = 0 then
12423 ComCtl32_Module := LoadLibrary( 'comctl32.dll' );
12424 @ Proc := GetProcAddress( ComCtl32_Module, 'InitCommonControlsEx' );
12425 if Assigned( Proc ) then
12426 begin
12427 ICC.dwSize := Sizeof( ICC );
12428 ICC.dwICC := dwICC;
12429 Proc( @ ICC );
12430 end;
12431 end;
12432 //[END DoInitCommonControls]
12434 const size_TRect = 16; // used often in assembler versions of code
12437 {$IFDEF ASM_VERSION}
12438 const
12439 EmptyString: String = '';
12441 //[PROCEDURE EAX2PChar]
12442 procedure EAX2PChar;
12444 TEST EAX, EAX
12445 JNZ @@exit
12446 MOV EAX, offset[EmptyString]
12447 @@exit:
12448 end;
12450 //[PROCEDURE EDX2PChar]
12451 procedure EDX2PChar;
12453 TEST EDX, EDX
12454 JNZ @@exit
12455 MOV EDX, offset[EmptyString]
12456 @@exit:
12457 end;
12459 //[PROCEDURE ECX2PChar]
12460 procedure ECX2PChar;
12462 JECXZ @@convert
12464 @@convert:
12465 MOV ECX, offset[EmptyString]
12466 @@exit:
12467 end;
12469 //[PROCEDURE RemoveStr]
12470 procedure RemoveStr;
12472 { <- [ESP+4] = string to remove
12473 -> ESP := ESP + 4
12474 EAX = 0
12476 POP EAX
12477 XCHG EAX, [ESP]
12478 PUSH EAX
12479 MOV EAX, ESP
12480 CALL System.@LStrClr
12481 POP EAX
12482 end;
12483 {$ELSE ASM_VERSION}
12484 {$ENDIF ASM_VERSION}
12487 //[PROCEDURE MsgOK]
12488 procedure MsgOK( const S: String );
12489 begin
12490 MsgBox( S, MB_OK );
12491 end;
12493 {$IFDEF ASM_VERSION}
12494 //[function MsgBox]
12495 function MsgBox( const S: String; Flags: DWORD ): DWORD;
12497 PUSH EDX
12498 PUSH EAX
12500 MOV ECX, [Applet]
12501 XOR EAX, EAX
12502 JECXZ @@1
12503 MOV EAX, [ECX].TControl.fCaption
12504 @@1:
12505 XCHG EAX, [ESP]
12506 PUSH EAX
12507 PUSH 0
12508 CALL MessageBox
12509 end;
12510 {$ELSE ASM_VERSION} //Pascal
12511 function MsgBox( const S: String; Flags: DWORD ): DWORD;
12512 var Title: PChar;
12513 begin
12514 Title := nil;
12515 if assigned( Applet ) then
12516 begin
12517 Title := PChar( Applet.fCaption );
12518 end;
12519 Result := MessageBox( 0 {Wnd}, PChar( S ), Title, Flags );
12520 end;
12521 //[END MsgBox]
12522 {$ENDIF ASM_VERSION}
12524 //[function ShowMsg]
12525 function ShowMsg( const S: String; Flags: DWORD ): DWORD;
12526 var Title: PChar;
12527 Wnd: HWnd;
12528 begin
12529 Title := nil;
12530 Wnd := 0;
12531 if assigned( Applet ) then
12532 begin
12533 Title := PChar( Applet.fCaption );
12534 Wnd := Applet.Handle;
12535 end;
12536 Result := MessageBox( Wnd, PChar( S ), Title, Flags );
12537 end;
12538 //[END ShowMsg]
12540 //[procedure ShowMessage]
12541 procedure ShowMessage( const S: String );
12542 begin
12543 ShowMsg( S, MB_OK or MB_SETFOREGROUND );
12544 end;
12545 //[ENDe ShowMessage]
12547 //[procedure OKClick]
12548 procedure OKClick( Dialog, Btn: PControl );
12549 var Rslt: Integer;
12550 begin
12551 Rslt := -1;
12552 if Btn <> nil then
12553 Rslt := Btn.Tag;
12554 Dialog.ModalResult := Rslt;
12555 Dialog.Close;
12556 end;
12557 //[END OKClick]
12559 //[procedure KeyClick]
12560 procedure KeyClick( Dialog, Btn: PControl; var Key: Longint; Shift: DWORD );
12561 begin
12562 if (Key = VK_RETURN) or (Key = VK_ESCAPE) then
12563 begin
12564 if Key = VK_ESCAPE then
12565 Btn := nil;
12566 OKClick( Dialog, Btn );
12567 end;
12568 end;
12569 //[ENDe KeyClick]
12571 //[procedure CloseMsg]
12572 procedure CloseMsg( Dummy, Dialog: PControl; var Accept: Boolean );
12573 begin
12574 Accept := FALSE;
12575 Dialog.ModalResult := -1;
12576 end;
12577 //[ENDe CloseMsg]
12579 //[function ShowQuestionEx]
12580 function ShowQuestionEx( const S: String; Answers: String; CallBack: TOnEvent ): Integer;
12581 {$IFDEF F_P105ORBELOW}
12582 type POnEvent = ^TOnEvent;
12583 PONKey = ^TOnKey;
12584 var M: TMethod;
12585 {$ENDIF F_P105ORBELOW}
12586 var Dialog: PControl;
12587 Buttons: PList;
12588 Btn: PControl;
12589 AppTermFlag: Boolean;
12590 Lab: PControl;
12591 Y, W, I: Integer;
12592 Title: String;
12593 DlgWnd: HWnd;
12594 AppCtl: PControl;
12595 begin
12596 AppTermFlag := AppletTerminated;
12597 AppCtl := Applet;
12598 AppletTerminated := FALSE;
12599 Title := 'Information';
12600 if pos( '/', Answers ) > 0 then
12601 Title := 'Question';
12602 if Applet <> nil then
12603 Title := Applet.Caption;
12604 Dialog := NewForm( Applet, Title ).SetSize( 300, 40 );
12605 Dialog.Style := Dialog.Style and not (WS_MINIMIZEBOX or WS_MAXIMIZEBOX);
12606 Dialog.OnClose := TOnEventAccept( MakeMethod( Dialog, @CloseMsg ) );
12607 Dialog.Margin := 8;
12608 Lab := NewEditbox( Dialog, [ eoMultiline, eoReadonly, eoNoHScroll, eoNoVScroll ] ).SetSize( 278, 20 );
12609 Lab.HasBorder := FALSE;
12610 Lab.Color := clBtnFace;
12611 Lab.Caption := S;
12612 Lab.Style := Lab.Style and not WS_TABSTOP;
12613 Lab.TabStop := FALSE;
12614 //Lab.LikeSpeedButton;
12616 //Lab.CreateWindow; //virtual!!! -- not needed, window created in Perform
12617 while TRUE do
12618 begin
12619 Y := HiWord( Lab.Perform( EM_POSFROMCHAR, Length( S ) - 1, 0 ) );
12620 if Y < Lab.Height - 20 then break;
12621 Lab.Height := Lab.Height + 4;
12622 if Lab.Height + 40 > GetSystemMetrics( SM_CYSCREEN ) then break;
12623 end;
12625 Buttons := NewList;
12626 W := 0;
12627 if Answers = '' then
12628 begin
12629 Btn := NewButton( Dialog, ' OK ' ).PlaceUnder;
12630 W := Btn.Width;
12631 Buttons.Add( Btn );
12633 else
12634 while Answers <> '' do
12635 begin
12636 Btn := NewButton( Dialog, ' ' + Parse( Answers, '/' ) + ' ' );
12637 Buttons.Add( Btn );
12638 if W = 0 then
12639 Btn.PlaceUnder
12640 else
12641 Btn.PlaceRight;
12642 Btn.AutoSize( TRUE );
12643 if W > 0 then
12644 begin
12645 //Inc( W, 6 );
12646 Btn.Left := Btn.Left + 6;
12647 end;
12648 W := Btn.BoundsRect.Right + 12;
12649 end;
12650 if Dialog.ClientWidth < W then
12651 Dialog.ClientWidth := W;
12652 W := (Dialog.ClientWidth - W) div 2;
12653 for I := 0 to Buttons.Count-1 do
12654 begin
12655 Btn := Buttons.Items[ I ];
12656 Btn.Tag := I + 1;
12657 {$IFDEF F_P105ORBELOW}
12658 M := MakeMethod( Dialog, @OKClick );
12659 Btn.OnClick := POnEvent( @ M )^;
12660 M := MakeMethod( Dialog, @KeyClick );
12661 Btn.OnKeyDown := POnKey( @ M )^;
12662 {$ELSE}
12663 Btn.OnClick := TOnEvent( MakeMethod( Dialog, @OKClick ) );
12664 Btn.OnKeyDown := TOnKey( MakeMethod( Dialog, @KeyClick ) );
12665 {$ENDIF}
12666 Btn.Left := Btn.Left + W;
12667 if I = 0 then
12668 begin
12669 Btn.ResizeParentBottom;
12670 Dialog.ActiveControl := Btn;
12671 end;
12672 end;
12673 Dialog.CenterOnParent.Tabulate.CanResize := FALSE;
12674 Buttons.Free;
12676 if Assigned( CallBack ) then
12677 CallBack( Dialog );
12678 Dialog.CreateWindow; // virtual!!!
12680 if (Applet <> nil) and Applet.IsApplet then
12681 begin
12682 Dialog.ShowModal;
12683 Result := Dialog.ModalResult;
12684 Dialog.Free;
12686 else
12687 begin
12688 DlgWnd := Dialog.Handle;
12689 while IsWindow( DlgWnd ) and (Dialog.ModalResult = 0) do
12690 Dialog.ProcessMessage;
12691 Result := Dialog.ModalResult;
12692 Dialog.Free;
12693 CreatingWindow := nil;
12694 Applet := AppCtl;
12695 end;
12697 AppletTerminated := AppTermFlag;
12698 end;
12699 //[END ShowQuestionEx]
12701 //[function ShowQuestion]
12702 function ShowQuestion( const S: String; Answers: String ): Integer;
12703 begin
12704 Result := ShowQuestionEx( S, Answers, nil );
12705 end;
12706 //[END ShowQuestion]
12708 //[procedure ShowMsgModal]
12709 procedure ShowMsgModal( const S: String );
12710 begin
12711 ShowQuestion( S, '' );
12712 end;
12713 //[ENDe ShowMsgModal]
12715 //[procedure SpeakerBeep]
12716 procedure SpeakerBeep( Freq: Word; Duration: DWORD );
12717 begin
12718 if WinVer >= wvNT then
12719 Windows.Beep( Freq, Duration )
12720 else
12721 begin
12722 if Freq < 18 then Exit;
12723 Freq := 1193181 div Freq;
12724 if Freq = 0 then Exit;
12726 mov al,0b6H
12727 out 43H,al
12728 mov ax,Freq
12729 //xchg al, ah
12730 out 42h,al
12731 xchg al, ah
12732 out 42h,al
12733 in al,61H
12734 or al,03H
12735 out 61H,al
12736 end {$IFDEF F_P} [ 'EAX' ] {$ENDIF} ;
12737 Sleep(Duration);
12739 in al,61H
12740 and al,0fcH
12741 out 61H,al
12742 end {$IFDEF F_P} [ 'EAX' ] {$ENDIF} ;
12743 end;
12744 end;
12745 //[ENDe SpeakerBeep]
12747 {++}(*
12748 //[API FormatMessage]
12749 function FormatMessage; external kernel32 name 'FormatMessageA';
12750 *){--}
12752 //[FUNCTION SysErrorMessage]
12753 function SysErrorMessage(ErrorCode: Integer): string;
12755 Len: Integer;
12756 Buffer: array[0..255] of Char;
12757 begin
12758 Len := FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM or
12759 FORMAT_MESSAGE_ARGUMENT_ARRAY, nil, ErrorCode, 0, Buffer,
12760 SizeOf(Buffer), nil);
12761 while (Len > 0) and (Buffer[Len - 1] in [#0..#32 {, '.'}]) do Dec(Len);
12762 SetString(Result, Buffer, Len);
12763 end;
12764 //[END SysErrorMessage]
12766 //[function MakeMethod]
12767 function MakeMethod( Data, Code: Pointer ): TMethod;
12768 begin
12769 Result.Data := Data;
12770 Result.Code := Code;
12771 end;
12772 //[END MakeMethod]
12774 //[function GetShiftState]
12775 function GetShiftState: DWORD;
12776 begin
12777 Result := 0;
12778 if GetKeyState( VK_SHIFT ) < 0 then
12779 Result := Result or MK_SHIFT;
12780 if GetKeyState( VK_CONTROL ) < 0 then
12781 Result := Result or MK_CONTROL;
12782 //if LONGBOOL(Msg.lParam and $20000000) then
12783 if GetKeyState( VK_MENU ) < 0 then
12784 Result := Result or MK_ALT;
12785 end;
12786 //[END GetShiftState]
12788 //[FUNCTION MakeRect]
12789 {$IFDEF ASM_VERSION}
12790 function MakeRect( Left, Top, Right, Bottom: Integer ): TRect; stdcall;
12792 PUSH ESI
12793 PUSH EDI
12795 MOV EDI, @Result
12796 LEA ESI, [Left]
12798 MOVSD
12799 MOVSD
12800 MOVSD
12801 MOVSD
12803 POP EDI
12804 POP ESI
12805 end;
12806 {$ELSE ASM_VERSION} //Pascal
12807 function MakeRect( Left, Top, Right, Bottom: Integer ): TRect; stdcall;
12808 begin
12809 Result.Left := Left;
12810 Result.Top := Top;
12811 Result.Right:= Right;
12812 Result.Bottom := Bottom;
12813 end;
12814 {$ENDIF ASM_VERSION}
12815 //[END MakeRect]
12817 //[FUNCTION RectsEqual]
12818 {$IFDEF ASM_VERSION}
12819 function RectsEqual( const R1, R2: TRect ): Boolean;
12821 //LEA EAX, [R1]
12822 //LEA EDX, [R2]
12823 MOV ECX, size_TRect
12824 CALL CompareMem
12825 end;
12826 {$ELSE ASM_VERSION} //Pascal
12827 function RectsEqual( const R1, R2: TRect ): Boolean;
12828 begin
12829 Result := CompareMem( @R1, @R2, Sizeof( TRect ) );
12830 end;
12831 {$ENDIF ASM_VERSION}
12832 //[END RectsEqual]
12834 //[function RectsIntersected]
12835 function RectsIntersected( const R1, R2: TRect ): Boolean;
12836 begin
12837 Result := ((R1.Left <= R2.Left) and (R1.Right > R2.Left ) or
12838 (R1.Left <= R2.Right) and (R1.Right >= R2.Right) or
12839 (R1.Left >= R2.Left) and (R1.Right <= R2.Right))
12841 ((R1.Top <= R2.Top) and (R1.Bottom > R2.Top) or
12842 (R1.Top <= R2.Bottom) and (R1.Bottom >= R2.Bottom) or
12843 (R1.Top >= R2.Top) and (R1.Bottom <= R2.Bottom)) ;
12844 end;
12845 //[END RectsIntersected]
12848 //[FUNCTION PointInRect]
12849 {$IFDEF ASM_VERSION}
12850 function PointInRect( const P: TPoint; const R: TRect ): Boolean;
12852 PUSH ESI
12853 MOV ECX, EAX
12854 MOV ESI, EDX
12855 LODSD
12856 CMP EAX, [ECX]
12857 JG @@fail
12858 LODSD
12859 CMP EAX, [ECX+4]
12860 JG @@fail
12861 LODSD
12862 CMP [ECX], EAX
12863 JG @@fail
12864 LODSD
12865 CMP [ECX+4], EAX
12866 @@fail: SETLE AL
12867 POP ESI
12868 end;
12869 {$ELSE ASM_VERSION} //Pascal
12870 function PointInRect( const P: TPoint; const R: TRect ): Boolean;
12871 begin
12872 Result := (P.x >= R.Left) and (P.x < R.Right)
12873 and (P.y >= R.Top) and (P.y < R.Bottom);
12874 end;
12875 {$ENDIF ASM_VERSION}
12876 //[END PointInRect]
12878 //[FUNCTION MakePoint]
12879 {$IFDEF ASM_VERSION}
12880 function MakePoint( X, Y: Integer ): TPoint;
12882 MOV ECX, @Result
12883 MOV [ECX].TPoint.x, EAX
12884 MOV [ECX].TPoint.y, EDX
12885 end;
12886 {$ELSE ASM_VERSION} //Pascal
12887 function MakePoint( X, Y: Integer ): TPoint;
12888 begin
12889 Result.x := X;
12890 Result.y := Y;
12891 end;
12892 {$ENDIF ASM_VERSION}
12893 //[END MakePoint]
12895 //[FUNCTION MakeFlags]
12896 {$IFDEF ASM_VERSION}
12897 function MakeFlags( FlgSet: PDWORD; FlgArray: array of Integer): Integer;
12899 PUSH EBX
12900 PUSH ESI
12901 MOV EBX, [EAX]
12902 MOV ESI, EDX
12903 XOR EDX, EDX
12904 INC ECX
12905 JZ @@exit
12906 @@loo:
12907 LODSD
12908 TEST EAX, EAX
12909 JGE @@ge
12910 NOT EAX
12911 TEST BL, 1
12912 JZ @@or
12913 DEC EBX
12914 @@ge:
12915 TEST BL, 1
12916 JZ @@nx
12917 @@or:
12918 OR EDX, EAX
12919 @@nx:
12920 SHR EBX, 1
12921 LOOP @@loo
12923 @@exit:
12924 XCHG EAX, EDX
12925 POP ESI
12926 POP EBX
12927 end;
12928 {$ELSE ASM_VERSION} //Pascal
12929 function MakeFlags( FlgSet: PDWORD; FlgArray: array of Integer): Integer;
12930 var I : Integer;
12931 Mask : DWORD;
12932 begin
12933 Result := 0;
12934 Mask := FlgSet^;
12935 for I := 0 to High( FlgArray ) do
12936 begin
12937 if (FlgArray[ I ] < 0) and not LongBool( Mask and 1 ) then
12938 Result := Result or not FlgArray[ I ]
12939 else
12940 if (FlgArray[ I ] >= 0) and LongBool( Mask and 1 ) then
12941 Result := Result or FlgArray[ I ];
12942 Mask := Mask shr 1;
12943 end;
12944 end;
12945 {$ENDIF ASM_VERSION}
12946 //[END MakeFlags]
12948 //[procedure HelpFastIncNum2Els]
12949 procedure HelpFastIncNum2Els( DataArray: Pointer; Value, Count: Integer );
12951 PUSH ESI
12952 PUSH EDI
12953 {$IFDEF F_P}
12954 MOV ESI, [DataArray]
12955 MOV EDX, [Value]
12956 MOV ECX, [Count]
12957 {$ELSE DELPHI}
12958 MOV ESI, EAX
12959 {$ENDIF F_P/DELPHI}
12960 MOV EDI, ESI
12963 @@1:
12964 LODSD
12965 ADD EAX, EDX
12966 STOSD
12967 LOOP @@1
12969 POP EDI
12970 POP ESI
12971 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
12972 //[ENDe HelpFastIncNum2Els]
12974 //[procedure Swap]
12975 procedure Swap( var X, Y: Integer );
12976 {$IFDEF F_P}
12977 var Tmp: Integer;
12978 begin
12979 Tmp := X;
12980 X := Y;
12981 Y := Tmp;
12982 end;
12983 {$ELSE DELPHI}
12985 MOV ECX, [EDX]
12986 XCHG ECX, [EAX]
12987 MOV [EDX], ECX
12988 end;
12989 //[ENDe Swap]
12990 {$ENDIF F_P/DELPHI}
12992 //[function Min]
12993 function Min( X, Y: Integer ): Integer;
12995 {$IFDEF F_P}
12996 MOV EAX, [X]
12997 MOV EDX, [Y]
12998 {$ENDIF F_P}
12999 {$IFDEF USE_CMOV}
13000 CMP EAX, EDX
13001 CMOVG EAX, EDX
13002 {$ELSE}
13003 CMP EAX, EDX
13004 JLE @@exit
13005 MOV EAX, EDX
13006 @@exit:
13007 {$ENDIF}
13008 end {$IFDEF F_P} [ 'EAX', 'EDX' ] {$ENDIF};
13009 //[END Min]
13011 //[function Max]
13012 function Max( X, Y: Integer ): Integer;
13014 {$IFDEF F_P}
13015 MOV EAX, [X]
13016 MOV EDX, [Y]
13017 {$ENDIF F_P}
13018 {$IFDEF USE_CMOV}
13019 CMP EAX, EDX
13020 CMOVL EAX, EDX
13021 {$ELSE}
13022 CMP EAX, EDX
13023 JGE @@exit
13024 MOV EAX, EDX
13025 @@exit:
13026 {$ENDIF}
13027 end {$IFDEF F_P} [ 'EAX', 'EDX' ] {$ENDIF};
13028 //[END Max]
13030 //[function Abs]
13031 function Abs( X: Integer ): Integer;
13033 {$IFDEF F_P}
13034 MOV EAX, [X]
13035 {$ENDIF F_P}
13036 TEST EAX, EAX
13037 JGE @@1
13038 NEG EAX
13039 @@1:
13040 end {$IFDEF F_P} [ 'EAX' ] {$ENDIF};
13041 //[END Abs]
13043 //[function Sgn]
13044 function Sgn( X: Integer ): Integer;
13046 CMP EAX, 0
13047 {$IFDEF USE_CMOV}
13048 MOV EDX, -1
13049 CMOVL EAX, EDX
13050 MOV EDX, 1
13051 CMOVG EAX, EDX
13052 {$ELSE}
13053 JZ @@exit
13054 MOV EAX, 1
13055 JG @@exit
13056 MOV EAX, -1
13057 @@exit:
13058 {$ENDIF}
13059 end;
13060 //[END Sgn]
13062 //[function iSqrt]
13063 function iSQRT( X: Integer ): Integer;
13064 var I, N: Integer;
13065 begin
13066 Result := 0;
13067 while Result < X do
13068 begin
13069 I := 1;
13070 while I > 0 do
13071 begin
13072 N := (Result + I) * (Result + I);
13073 if N > X then
13074 begin
13075 I := I shr 1;
13076 break;
13078 else
13079 if N = X then
13080 begin
13081 Result := Result + I;
13082 Exit;
13083 end;
13084 I := I shl 1;
13085 end;
13086 if I <= 0 then Exit;
13087 Result := Result + I;
13088 end;
13089 end;
13090 //[END iSqrt]
13092 {$IFDEF ASM_VERSION}
13093 //[PROCEDURE StartDC]
13094 procedure StartDC;
13096 { <- EBX : PBitmap
13097 -> EAX = dc
13098 [ESP+8] = var dc
13099 [ESP+4] = var SaveBmp
13101 PUSH 0
13102 CALL CreateCompatibleDC
13103 POP EDX
13104 PUSH EAX
13105 PUSH EDX
13106 MOV EAX, EBX
13107 CALL [EBX].TBitmap.fDetachCanvas
13108 MOV EAX, EBX
13109 CALL TBitmap.GetHandle
13110 PUSH EAX
13111 PUSH dword ptr [ESP+8]
13112 CALL SelectObject
13113 POP EDX
13114 PUSH EAX
13115 PUSH EDX
13116 MOV EAX, [ESP+8]
13117 end;
13118 //[END StartDC]
13120 //[procedure FinishDC]
13121 procedure FinishDC;
13123 POP ECX
13124 POP EAX
13125 POP EDX
13126 PUSH ECX
13127 PUSH EDX
13128 PUSH EAX
13129 PUSH EDX
13130 CALL SelectObject
13131 CALL DeleteDC
13132 end;
13133 //[ENDe FinishDC]
13134 {$ELSE ASM_VERSION}
13135 {$ENDIF ASM_VERSION}
13137 //[procedure FastIncNum2Elements]
13138 procedure FastIncNum2Elements( List: TList; FromIdx, Count, Value: Integer );
13139 begin
13140 HelpFastIncNum2Els( @List.fItems[ FromIdx ], Value, Count );
13141 end;
13143 //[function EnumDynHandlers FORWARD DECLARATION]
13144 function EnumDynHandlers( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
13145 forward;
13147 //[procedure DummyObjProc]
13148 procedure DummyObjProc( Sender: PObj );
13149 begin
13150 end;
13152 //[procedure DummyObjProcParam]
13153 procedure DummyObjProcParam( Sender: PObj; Param: Pointer );
13154 begin
13155 end;
13157 //[procedure DummyPaintProc]
13158 procedure DummyPaintProc( Sender: PControl; DC: HDC );
13159 begin
13160 end;
13162 //[procedure Free_And_Nil]
13163 procedure Free_And_Nil( var Obj );
13164 var Obj1: PObj;
13165 begin
13166 Obj1 := PObj( Obj );
13167 Pointer( Obj ) := nil;
13168 Obj1.Free;
13169 end;
13170 //[ENDe Free_And_Nil]
13179 { _TObj }
13181 //[procedure _TObj.Init]
13182 procedure _TObj.Init;
13183 begin
13184 {$IFDEF _D2orD3}
13185 FillChar( Pointer( Integer(@Self) + 4 )^, Sizeof( Self ) - 4, 0 );
13186 {$ENDIF}
13187 end;
13190 //[function _TObj.VmtAddr]
13191 function _TObj.VmtAddr: Pointer;
13193 MOV EAX, [EAX]
13194 end;
13196 { TObj }
13198 class function TObj.AncestorOfObject(Obj: Pointer): Boolean;
13200 MOV ECX, [EAX]
13201 MOV EAX, EDX
13202 JMP @@loop1
13203 @@loop:
13204 MOV EAX,[EAX]
13205 @@loop1:
13206 TEST EAX,EAX
13207 JE @@exit
13208 CMP EAX,ECX
13209 JNE @@loop
13210 @@success:
13211 MOV AL,1
13212 @@exit:
13213 end;
13217 {$IFDEF ASM_VERSION}
13218 constructor TObj.Create;
13220 //CALL System.@ObjSetup - Generated always by compiler
13221 //JZ @@exit
13223 PUSH EAX
13224 MOV EDX, [EAX]
13225 CALL dword ptr [EDX]
13226 POP EAX
13228 @@exit:
13229 end;
13230 {$ELSE ASM_VERSION} //Pascal
13231 constructor TObj.Create;
13232 begin
13233 Init;
13234 {++}(* inherited; *){--}
13235 end;
13236 {$ENDIF ASM_VERSION}
13238 {$IFDEF ASM_VERSION}
13239 //[procedure TObj.DoDestroy]
13240 procedure TObj.DoDestroy;
13242 MOV EDX, [EAX].fRefCount
13243 SAR EDX, 1
13244 JZ @@1
13245 JC @@exit
13246 DEC [EAX].fRefCount
13249 @@1: JC @@exit
13250 MOV EDX, [EAX]
13251 CALL dword ptr [EDX + 4]
13252 @@exit:
13253 end;
13254 {$ELSE ASM_VERSION} //Pascal
13255 procedure TObj.DoDestroy;
13256 begin
13257 if fRefCount <> 0 then
13258 begin
13259 if not LongBool( fRefCount and 1) then
13260 Dec( fRefCount );
13262 else
13263 Destroy;
13264 end;
13265 {$ENDIF ASM_VERSION}
13267 {$IFDEF ASM_VERSION}
13268 //[procedure TObj.RefDec]
13269 procedure TObj.RefDec;
13271 SUB [EAX].fRefCount, 2
13272 JGE @@exit
13273 TEST [EAX].fRefCount, 1
13274 JZ @@exit
13275 MOV EDX, [EAX]
13276 PUSH dword ptr [EDX+4]
13277 @@exit:
13278 end;
13279 {$ELSE ASM_VERSION} //Pascal
13280 procedure TObj.RefDec;
13281 begin
13282 Dec( fRefCount, 2 );
13283 if (fRefCount < 0) and LongBool(fRefCount and 1) then
13284 Destroy;
13285 end;
13286 {$ENDIF ASM_VERSION}
13288 //[procedure TObj.RefInc]
13289 procedure TObj.RefInc;
13290 begin
13291 Inc( fRefCount, 2 );
13292 end;
13295 //[function TObj.VmtAddr]
13296 function TObj.VmtAddr: Pointer;
13298 MOV EAX, [EAX - 4]
13299 end;
13301 //[function TObj.InstanceSize]
13302 function TObj.InstanceSize: Integer;
13304 MOV EAX, [EAX]
13305 MOV EAX,[EAX-4]
13306 end;
13309 //[procedure TObj.Free]
13310 procedure TObj.Free;
13311 {$IFDEF F_P}
13312 begin
13313 if Self <> nil then
13314 DoDestroy;
13315 end;
13316 {$ELSE DELPHI}
13318 TEST EAX,EAX
13319 JNE DoDestroy
13320 end;
13321 {$ENDIF F_P/DELPHI}
13323 {$IFDEF ASM_VERSION}
13324 destructor TObj.Destroy;
13326 PUSH EAX
13327 CALL Final
13328 POP EAX
13329 XOR EDX, EDX
13330 CALL System.@FreeMem
13331 //CALL System.@Dispose
13332 end;
13333 {$ELSE ASM_VERSION} //Pascal
13334 destructor TObj.Destroy;
13335 begin
13336 Final;
13337 {$IFDEF DEBUG_ENDSESSION}
13338 if EndSession_Initiated then
13339 LogFileOutput( GetStartDir + 'es_debug.txt',
13340 'FINALLED: ' + Int2Hex( DWORD( @ Self ), 8 ) );
13341 {$ENDIF}
13343 Dispose( @Self );
13344 {+} {++}(*
13345 inherited; *){--}
13346 end;
13347 {$ENDIF ASM_VERSION}
13349 {++}(*
13350 //[procedure TObj.Init]
13351 procedure TObj.Init;
13352 begin
13354 end;
13355 *){--}
13357 {$IFDEF ASM_VERSION}
13358 //[procedure TObj.Final]
13359 procedure TObj.Final;
13360 asm //cmd //opd
13361 XOR ECX, ECX
13362 XCHG ECX, [EAX].fOnDestroy.TMethod.Code
13363 JECXZ @@doAutoFree
13364 PUSH EAX
13365 XCHG EDX, EAX
13366 MOV EAX, [EDX].fOnDestroy.TMethod.Data
13367 CALL ECX
13368 POP EAX
13369 @@doAutoFree:
13370 XOR ECX, ECX
13371 XCHG ECX, [EAX].fAutoFree
13372 JECXZ @@exit
13373 PUSH ESI
13374 PUSH ECX
13375 MOV ESI, [ECX].TList.fItems
13376 MOV ECX, [ECX].TList.fCount
13377 @@freeloop:
13378 LODSD
13379 XCHG EDX, EAX
13380 LODSD
13381 PUSH ECX
13382 CALL EDX
13383 POP ECX
13384 DEC ECX
13385 LOOP @@freeloop
13386 POP EAX
13387 CALL TObj.Free
13388 POP ESI
13389 @@exit:
13390 end;
13391 {$ELSE ASM_VERSION} //Pascal
13392 procedure TObj.Final;
13393 var I: Integer;
13394 ProcMethod: TMethod;
13395 Proc: TObjectMethod Absolute ProcMethod;
13396 begin
13397 if Assigned( fOnDestroy ) then
13398 begin
13399 fOnDestroy( @Self );
13400 fOnDestroy := nil;
13401 end;
13402 if fAutoFree <> nil then
13403 begin
13404 for I := 0 to fAutoFree.fCount div 2 - 1 do
13405 begin
13406 ProcMethod.Code := fAutoFree.fItems[ I * 2 ];
13407 ProcMethod.Data := fAutoFree.fItems[ I * 2 + 1 ];
13409 Proc;
13410 {+}{++}(*
13412 MOV EAX, [ProcMethod.Data]
13413 {$IFDEF F_P}
13414 PUSH EAX
13415 {$ENDIF F_P}
13416 MOV ECX, [ProcMethod.Code]
13417 CALL ECX
13418 end {$IFDEF F_P}[ 'EAX', 'EDX', 'ECX' ]{$ENDIF};
13419 *){--}
13420 end;
13421 fAutoFree.Free;
13422 fAutoFree := nil;
13423 end;
13424 end;
13425 {$ENDIF ASM_VERSION}
13427 {$IFDEF ASM_VERSION}
13428 //[procedure TObj.Add2AutoFree]
13429 procedure TObj.Add2AutoFree(Obj: PObj);
13430 asm //cmd //opd
13431 PUSH EBX
13432 PUSH EDX
13433 XCHG EBX, EAX
13434 MOV EAX, [EBX].fAutoFree
13435 TEST EAX, EAX
13436 JNZ @@1
13437 CALL NewList
13438 MOV [EBX].fAutoFree, EAX
13439 @@1: MOV EBX, EAX
13440 XOR EDX, EDX
13441 POP ECX
13442 CALL TList.Insert
13443 XCHG EAX, EBX
13444 XOR EDX, EDX
13445 MOV ECX, offset TObj.Free
13446 //XOR ECX, ECX
13447 CALL TList.Insert
13448 POP EBX
13449 end;
13450 {$ELSE ASM_VERSION} //Pascal
13451 procedure TObj.Add2AutoFree(Obj: PObj);
13452 begin
13453 if fAutoFree = nil then
13454 fAutoFree := NewList;
13455 fAutoFree.Insert( 0, Obj );
13456 fAutoFree.Insert( 0, Pointer( @TObj.Free ) );
13457 end;
13458 {$ENDIF ASM_VERSION}
13460 {$IFDEF ASM_VERSION}
13461 //[procedure TObj.Add2AutoFreeEx]
13462 procedure TObj.Add2AutoFreeEx( Proc: TObjectMethod );
13463 asm //cmd //opd
13464 PUSH EBX
13465 XCHG EAX, EBX
13466 MOV EAX, [EBX].fAutoFree
13467 TEST EAX, EAX
13468 JNZ @@1
13469 CALL NewList
13470 MOV [EBX].fAutoFree, EAX
13471 @@1: XOR EDX, EDX
13472 MOV ECX, [EBP+12] // Data
13473 MOV EBX, EAX
13474 CALL TList.Insert
13475 XCHG EAX, EBX
13476 XOR EDX, EDX
13477 MOV ECX, [EBP+8] // Code
13478 CALL TList.Insert
13479 POP EBX
13480 end;
13481 {$ELSE ASM_VERSION} //Pascal
13482 procedure TObj.Add2AutoFreeEx( Proc: TObjectMethod );
13483 {$IFDEF F_P}
13484 var Ptr1, Ptr2: Pointer;
13485 {$ENDIF F_P}
13486 begin
13487 if fAutoFree = nil then
13488 fAutoFree := NewList;
13489 {$IFDEF F_P}
13491 MOV EAX, [Proc]
13492 MOV [Ptr1], EAX
13493 MOV EAX, [Proc+4]
13494 MOV [Ptr2], EAX
13495 end [ 'EAX' ];
13496 fAutoFree.Insert( 0, Ptr2 );
13497 fAutoFree.Insert( 0, Ptr1 );
13498 {$ELSE DELPHI}
13499 fAutoFree.Insert( 0, Pointer( TMethod( Proc ).Data ) );
13500 fAutoFree.Insert( 0, Pointer( TMethod( Proc ).Code ) );
13501 {$ENDIF}
13502 end;
13503 {$ENDIF ASM_VERSION}
13519 { TList }
13521 {$IFDEF USE_CONSTRUCTORS}
13522 //[function NewList]
13523 function NewList: PList;
13524 begin
13525 New( Result, Create );
13526 //Result.fAddBy := 4;
13527 end;
13528 //[END NewList]
13530 //[procedure TList.Init]
13531 procedure TList.Init;
13532 begin
13533 inherited;
13534 fAddBy := 4;
13535 end;
13536 {$ELSE not_USE_CONSTRUCTORS}
13537 //[function NewList]
13538 function NewList: PList;
13539 begin
13541 New( Result, Create );
13542 {+} {++}(* Result := PList.Create; *){--}
13543 //Result.fAddBy := 4;
13544 end;
13545 //[END NewList]
13546 {$ENDIF USE_CONSTRUCTORS}
13548 {$IFDEF ASM_VERSION}
13549 destructor TList.Destroy;
13551 PUSH EAX
13552 CALL TList.Clear
13553 POP EAX
13554 CALL TObj.Destroy
13555 end;
13556 {$ELSE ASM_VERSION} //Pascal
13557 destructor TList.Destroy;
13558 begin
13559 Clear;
13560 inherited;
13561 end;
13562 {$ENDIF ASM_VERSION}
13564 {$IFDEF ASM_VERSION}
13565 //[procedure TList.Release]
13566 procedure TList.Release;
13568 TEST EAX, EAX
13569 JZ @@e
13570 MOV ECX, [EAX].fCount
13571 JECXZ @@e
13572 MOV EDX, [EAX].fItems
13573 PUSH EAX
13574 @@1:
13575 MOV EAX, [EDX+ECX*4-4]
13576 TEST EAX, EAX
13577 JZ @@2
13578 PUSH EDX
13579 PUSH ECX
13580 CALL System.@FreeMem
13581 POP ECX
13582 POP EDX
13583 @@2: LOOP @@1
13584 POP EAX
13585 @@e: CALL TObj.Free
13586 end;
13587 {$ELSE ASM_VERSION} //Pascal
13588 procedure TList.Release;
13589 var I: Integer;
13590 begin
13591 if @ Self = nil then Exit;
13592 for I := 0 to fCount - 1 do
13593 if fItems[ I ] <> nil then
13594 FreeMem( fItems[ I ] );
13595 Free;
13596 end;
13597 {$ENDIF ASM_VERSION}
13599 //[procedure TList.ReleaseObjects]
13600 procedure TList.ReleaseObjects;
13601 var I: Integer;
13602 begin
13603 if @ Self = nil then Exit;
13604 for I := fCount-1 downto 0 do
13605 PObj( fItems[ I ] ).Free;
13606 Free;
13607 end;
13609 {$IFDEF ASM_VERSION}
13610 //[procedure TList.SetCapacity]
13611 procedure TList.SetCapacity( Value: Integer );
13613 CMP EDX, [EAX].fCount
13614 {$IFDEF USE_CMOV}
13615 CMOVL EDX, [EAX].fCount
13616 {$ELSE}
13617 JGE @@1
13618 MOV EDX, [EAX].fCount
13619 @@1: {$ENDIF}
13620 CMP EDX, [EAX].fCapacity
13621 JE @@exit
13623 MOV [EAX].fCapacity, EDX
13624 SAL EDX, 2
13625 LEA EAX, [EAX].fItems
13626 CALL System.@ReallocMem
13627 @@exit:
13628 end;
13629 {$ELSE ASM_VERSION} //Pascal
13630 //var NewItems: PPointerList;
13631 procedure TList.SetCapacity( Value: Integer );
13632 begin
13633 if Value < Count then
13634 Value := Count;
13635 if Value = fCapacity then Exit;
13636 ReallocMem( fItems, Value * Sizeof( Pointer ) );
13637 fCapacity := Value;
13638 end;
13639 {$ENDIF ASM_VERSION}
13641 {$IFDEF ASM_VERSION}
13642 //[procedure TList.Clear]
13643 procedure TList.Clear;
13645 PUSH [EAX].fItems
13646 XOR EDX, EDX
13647 MOV [EAX].fItems, EDX
13648 MOV [EAX].fCount, EDX
13649 MOV [EAX].fCapacity, EDX
13650 POP EAX
13651 CALL System.@FreeMem
13652 end;
13653 {$ELSE ASM_VERSION} //Pascal
13654 procedure TList.Clear;
13655 begin
13656 if fItems <> nil then
13657 FreeMem( fItems );
13658 fItems := nil;
13659 fCount := 0;
13660 fCapacity := 0;
13661 end;
13662 {$ENDIF ASM_VERSION}
13664 //[procedure TList.SetAddBy]
13665 procedure TList.SetAddBy(Value: Integer);
13666 begin
13667 if Value < 1 then Value := 1;
13668 fAddBy := Value;
13669 end;
13671 {$IFDEF ASM_VERSION}
13672 //[procedure TList.Add]
13673 procedure TList.Add( Value: Pointer );
13675 PUSH EDX
13676 LEA ECX, [EAX].fCount
13677 MOV EDX, [ECX]
13678 INC dword ptr [ECX]
13679 PUSH EDX
13680 CMP EDX, [EAX].fCapacity
13681 PUSH EAX
13682 JL @@ok
13684 MOV ECX, [EAX].fAddBy
13685 TEST ECX, ECX
13686 JNZ @@add
13687 MOV ECX, EDX
13688 SHR ECX, 2
13689 INC ECX
13690 @@add:
13691 ADD EDX, ECX
13692 CALL TList.SetCapacity
13693 @@ok:
13694 POP ECX // ECX = Self
13695 POP EAX // EAX = fCount -> Result (for TList.Insert)
13696 POP EDX // EDX = Value
13698 MOV ECX, [ECX].fItems
13699 MOV [ECX + EAX*4], EDX
13700 end;
13701 {$ELSE ASM_VERSION} //Pascal
13702 procedure TList.Add( Value: Pointer );
13703 begin
13704 //if fAddBy <= 0 then fAddBy := 4;
13705 if fCapacity <= Count then
13706 begin
13707 if fAddBy <= 0 then
13708 Capacity := Count + Min( 1000, Count div 4 + 1 )
13709 else
13710 Capacity := Count + fAddBy;
13711 end;
13712 fItems[ fCount ] := Value;
13713 Inc( fCount );
13714 end;
13715 {$ENDIF ASM_VERSION}
13717 //[procedure TList.Delete]
13718 procedure TList.Delete( Idx: Integer );
13719 begin
13720 {Assert( (Idx >= 0) and (Idx < fCount), 'TList.Delete: index out of bounds' );
13721 Move( fItems[ Idx + 1 ], fItems[ Idx ], Sizeof( Pointer ) * (Count - Idx - 1) );
13722 Dec( fCount );}
13723 DeleteRange( Idx, 1 );
13724 end;
13726 {$IFDEF ASM_VERSION}
13727 //[procedure TList.DeleteRange]
13728 procedure TList.DeleteRange(Idx, Len: Integer);
13729 asm //cmd //opd
13730 TEST ECX, ECX
13731 JLE @@exit
13732 CMP EDX, [EAX].fCount
13733 JGE @@exit
13734 PUSH EBX
13735 XCHG EBX, EAX
13736 LEA EAX, [EDX+ECX]
13737 CMP EAX, [EBX].fCount
13738 JBE @@1
13739 MOV ECX, [EBX].fCount
13740 SUB ECX, EDX
13741 @@1:
13742 MOV EAX, [EBX].fItems
13743 PUSH [EBX].fCount
13744 SUB [EBX].fCount, ECX
13745 MOV EBX, EDX
13746 LEA EDX, [EAX+EDX*4]
13747 LEA EAX, [EDX+ECX*4]
13748 ADD EBX, ECX
13749 POP ECX
13750 SUB ECX, EBX
13751 SHL ECX, 2
13752 CALL System.Move
13753 POP EBX
13754 @@exit:
13755 end;
13756 {$ELSE ASM_VERSION} //Pascal
13757 procedure TList.DeleteRange(Idx, Len: Integer);
13758 begin
13759 if Len <= 0 then Exit;
13760 if Idx >= Count then Exit;
13761 Assert( (Idx >= 0), 'TList.DeleteRange: index out of bounds' );
13762 if DWORD( Idx + Len ) > DWORD( Count ) then
13763 Len := Count - Idx;
13764 Move( fItems[ Idx + Len ], fItems[ Idx ], Sizeof( Pointer ) * (Count - Idx - Len) );
13765 Dec( fCount, Len );
13766 end;
13767 {$ENDIF ASM_VERSION}
13769 //[procedure TList.Remove]
13770 procedure TList.Remove(Value: Pointer);
13771 var I: Integer;
13772 begin
13773 I := IndexOf( Value );
13774 if I >= 0 then
13775 Delete( I );
13776 end;
13778 //[procedure TList.Put]
13779 procedure TList.Put( Idx: Integer; Value: Pointer );
13780 begin
13781 if Idx < 0 then Exit;
13782 if Idx >= Count then Exit;
13783 //Assert( (Idx >= 0) and (Idx < fCount), 'TList.Put: index out of bounds' );
13784 fItems[ Idx ] := Value;
13785 end;
13787 //[function TList.Get]
13788 function TList.Get( Idx: Integer ): Pointer;
13789 begin
13790 Result := nil;
13791 if Idx < 0 then Exit;
13792 if Idx >= fCount then Exit;
13793 //Assert( (Idx >= 0) and (Idx < fCount), 'TList.Get: index out of bounds' );
13794 Result := fItems[ Idx ];
13795 end;
13797 {$IFDEF ASM_VERSION}
13798 //[function TList.IndexOf]
13799 function TList.IndexOf( Value: Pointer ): Integer;
13801 PUSH EDI
13803 MOV EDI, [EAX].fItems
13804 MOV ECX, [EAX].fCount
13805 PUSH EDI
13806 DEC EAX // make "NZ" - EAX always <> 1
13807 MOV EAX, EDX
13808 REPNZ SCASD
13809 POP EDX
13810 {$IFDEF USE_CMOV}
13811 CMOVNZ EDI, EDX
13812 {$ELSE}
13813 JZ @@succ
13814 MOV EDI, EDX
13815 @@succ: {$ENDIF}
13817 MOV EAX, EDI
13819 SBB EAX, EDX
13820 SAR EAX, 2
13822 POP EDI
13823 end;
13824 {$ELSE ASM_VERSION} //Pascal
13825 function TList.IndexOf( Value: Pointer ): Integer;
13826 var I: Integer;
13827 begin
13828 Result := -1;
13829 for I := 0 to Count - 1 do
13830 begin
13831 if fItems[ I ] = Value then
13832 begin
13833 Result := I;
13834 break;
13835 end;
13836 end;
13837 end;
13838 {$ENDIF ASM_VERSION}
13840 {$IFDEF ASM_VERSION}
13841 //[procedure TList.Insert]
13842 procedure TList.Insert(Idx: Integer; Value: Pointer);
13844 PUSH ECX
13845 PUSH EAX
13846 PUSH [EAX].fCount
13847 PUSH EDX
13848 CALL TList.Add // don't matter what to add
13849 POP EDX // EDX = Idx, Eax = Count-1
13850 POP EAX
13851 SUB EAX, EDX
13853 SAL EAX, 2
13854 MOV ECX, EAX // ECX = (Count - Idx - 1) * 4
13855 POP EAX
13856 MOV EAX, [EAX].fItems
13857 LEA EAX, [EAX + EDX*4]
13858 JL @@1
13859 PUSH EAX
13860 LEA EDX, [EAX + 4]
13861 CALL System.Move
13863 POP EAX // EAX = @fItems[ Idx ]
13864 @@1:
13865 POP ECX // ECX = Value
13866 MOV [EAX], ECX
13867 end;
13868 {$ELSE ASM_VERSION} //Pascal
13869 procedure TList.Insert(Idx: Integer; Value: Pointer);
13870 begin
13871 Assert( (Idx >= 0) and (Idx <= Count), 'List index out of bounds' );
13872 Add( nil );
13873 if fCount > Idx then
13874 Move( FItems[ Idx ], FItems[ Idx + 1 ], (fCount - Idx - 1) * Sizeof( Pointer ) );
13875 FItems[ Idx ] := Value;
13876 end;
13877 {$ENDIF ASM_VERSION}
13879 {$IFDEF ASM_VERSION}
13880 //[procedure TList.MoveItem]
13881 procedure TList.MoveItem(OldIdx, NewIdx: Integer);
13883 CMP EDX, ECX
13884 JE @@exit
13886 CMP ECX, [EAX].fCount
13887 JGE @@exit
13889 PUSH EDI
13891 MOV EDI, [EAX].fItems
13892 PUSH dword ptr [EDI + EDX*4]
13893 PUSH ECX
13894 PUSH EAX
13895 CALL TList.Delete
13896 POP EAX
13897 POP EDX
13898 POP ECX
13900 POP EDI
13901 CALL TList.Insert
13902 @@exit:
13903 end;
13904 {$ELSE ASM_VERSION} //Pascal
13905 procedure TList.MoveItem(OldIdx, NewIdx: Integer);
13906 var Item: Pointer;
13907 //I: Integer;
13908 begin
13909 if OldIdx = NewIdx then Exit;
13910 if NewIdx >= Count then Exit;
13911 Item := Items[ OldIdx ];
13912 Delete( OldIdx );
13913 Insert( NewIdx, Item );
13914 end;
13915 {$ENDIF ASM_VERSION}
13917 {$IFDEF ASM_VERSION}
13918 //[function TList.Last]
13919 function TList.Last: Pointer;
13920 asm //cmd //opd
13921 MOV ECX, [EAX].fCount
13922 JECXZ @@0
13923 MOV EAX, [EAX].fItems
13924 DEC ECX
13925 MOV ECX, [EAX + ECX*4]
13926 @@0: XCHG EAX, ECX
13927 end;
13928 {$ELSE ASM_VERSION} //Pascal
13929 function TList.Last: Pointer;
13930 begin
13931 if Count = 0 then
13932 Result := nil
13933 else
13934 Result := Items[ Count-1 ];
13935 end;
13936 {$ENDIF ASM_VERSION}
13938 {$IFDEF ASM_VERSION}
13939 //[procedure TList.Swap]
13940 procedure TList.Swap(Idx1, Idx2: Integer);
13942 MOV EAX, [EAX].fItems
13943 PUSH dword ptr [EAX + EDX*4]
13944 PUSH ECX
13945 MOV ECX, [EAX + ECX*4]
13946 MOV [EAX + EDX*4], ECX
13947 POP ECX
13948 POP EDX
13949 MOV [EAX + ECX*4], EDX
13950 end;
13951 {$ELSE ASM_VERSION} //Pascal
13952 procedure TList.Swap(Idx1, Idx2: Integer);
13953 var Tmp: Pointer;
13954 begin
13955 Tmp := FItems[ Idx1 ];
13956 FItems[ Idx1 ] := FItems[ Idx2 ];
13957 FItems[ Idx2 ] := Tmp;
13958 end;
13959 {$ENDIF ASM_VERSION}
13961 //[procedure TList.SetCount]
13962 procedure TList.SetCount(const Value: Integer);
13963 begin
13964 if Value >= Count then exit;
13965 fCount := Value;
13966 end;
13968 //[procedure TList.Assign]
13969 procedure TList.Assign(SrcList: PList);
13970 begin
13971 Clear;
13972 if SrcList.fCount > 0 then
13973 begin
13974 Capacity := SrcList.fCount;
13975 fCount := SrcList.fCount;
13976 Move( SrcList.FItems[ 0 ], FItems[ 0 ], Sizeof( Pointer ) * fCount );
13977 end;
13978 end;
13980 { TListEx }
13982 //[function NewListEx]
13983 function NewListEx: PListEx;
13984 begin
13986 new( Result, Create );
13987 {+}{++}(*Result := PListEx.Create;*){--}
13988 Result.fList := NewList;
13989 Result.fObjects := NewList;
13990 end;
13991 //[END NewListEx]
13993 //[procedure TListEx.Add]
13994 procedure TListEx.Add(Value: Pointer);
13995 begin
13996 AddObj( Value, nil );
13997 end;
13999 //[procedure TListEx.AddObj]
14000 procedure TListEx.AddObj(Value, Obj: Pointer);
14001 var C: Integer;
14002 begin
14003 C := Count;
14004 fList.Add( Value );
14005 fObjects.Insert( C, Obj );
14006 end;
14008 //[procedure TListEx.Clear]
14009 procedure TListEx.Clear;
14010 begin
14011 fList.Clear;
14012 fObjects.Clear;
14013 end;
14015 //[procedure TListEx.Delete]
14016 procedure TListEx.Delete(Idx: Integer);
14017 begin
14018 DeleteRange( Idx, 1 );
14019 end;
14021 //[procedure TListEx.DeleteRange]
14022 procedure TListEx.DeleteRange(Idx, Len: Integer);
14023 begin
14024 fList.DeleteRange( Idx, Len );
14025 fObjects.DeleteRange( Idx, Len );
14026 end;
14028 //[destructor TListEx.Destroy]
14029 destructor TListEx.Destroy;
14030 begin
14031 fList.Free;
14032 fObjects.Free;
14033 inherited;
14034 end;
14036 //[function TListEx.GetAddBy]
14037 function TListEx.GetAddBy: Integer;
14038 begin
14039 Result := fList.AddBy;
14040 end;
14042 //[function TListEx.GetCount]
14043 function TListEx.GetCount: Integer;
14044 begin
14045 Result := fList.Count;
14046 end;
14048 //[function TListEx.GetEx]
14049 function TListEx.GetEx(Idx: Integer): Pointer;
14050 begin
14051 Result := fList.Items[ Idx ];
14052 end;
14054 //[function TListEx.IndexOf]
14055 function TListEx.IndexOf(Value: Pointer): Integer;
14056 begin
14057 Result := fList.IndexOf( Value );
14058 end;
14060 //[function TListEx.IndexOfObj]
14061 function TListEx.IndexOfObj(Obj: Pointer): Integer;
14062 begin
14063 Result := fObjects.IndexOf( Obj );
14064 end;
14066 //[procedure TListEx.Insert]
14067 procedure TListEx.Insert(Idx: Integer; Value: Pointer);
14068 begin
14069 InsertObj( Idx, Value, nil );
14070 end;
14072 //[procedure TListEx.InsertObj]
14073 procedure TListEx.InsertObj(Idx: Integer; Value, Obj: Pointer);
14074 begin
14075 fList.Insert( Idx, Value );
14076 fObjects.Insert( Idx, Obj );
14077 end;
14079 //[function TListEx.Last]
14080 function TListEx.Last: Pointer;
14081 begin
14082 Result := fList.Last;
14083 end;
14085 //[function TListEx.LastObj]
14086 function TListEx.LastObj: Pointer;
14087 begin
14088 Result := fObjects.Last;
14089 end;
14091 //[procedure TListEx.MoveItem]
14092 procedure TListEx.MoveItem(OldIdx, NewIdx: Integer);
14093 begin
14094 fList.MoveItem( OldIdx, NewIdx );
14095 fObjects.MoveItem( OldIdx, NewIdx );
14096 end;
14098 //[procedure TListEx.PutEx]
14099 procedure TListEx.PutEx(Idx: Integer; const Value: Pointer);
14100 begin
14101 fList.Items[ Idx ] := Value;
14102 end;
14104 //[procedure TListEx.Set_AddBy]
14105 procedure TListEx.Set_AddBy(const Value: Integer);
14106 begin
14107 fList.AddBy := Value;
14108 fObjects.AddBy := Value;
14109 end;
14111 //[procedure TListEx.Swap]
14112 procedure TListEx.Swap(Idx1, Idx2: Integer);
14113 begin
14114 fList.Swap( Idx1, Idx2 );
14115 fObjects.Swap( Idx1, Idx2 );
14116 end;
14135 { -- Window procedure -- }
14137 {$IFDEF ASM_VERSION} //!!//!!
14138 //[FUNCTION CallCtlWndProc]
14139 function CallCtlWndProc( Ctl: PControl; var Msg: TMsg ): Integer;
14140 begin
14141 Result := Ctl.WndProc( Msg );
14142 end;
14143 //[END CallCtlWndProc]
14145 //[function WndFunc]
14146 function WndFunc( W: HWnd; Msg: Cardinal; wParam, lParam: Integer )
14147 : Integer; stdcall;
14148 const size_TMsg = sizeof( TMsg );
14150 ADD ESP, -size_TMsg
14151 MOV EDX, ESP
14153 PUSH ESI
14154 PUSH EDI
14156 MOV EDI, EDX
14157 LEA ESI, [W]
14159 MOVSD
14160 MOVSD
14161 MOVSD
14162 MOVSD
14164 MOV EDI, EDX
14165 MOV EAX, [EDI]
14166 TEST EAX, EAX
14167 JZ @@self_is_nil
14169 MOV ECX, [CreatingWindow]
14170 JECXZ @@get_self_prop
14172 MOV [ECX].TControl.fHandle, EAX
14174 //set_self_prop:
14175 PUSH ECX
14176 PUSH ECX
14177 PUSH Offset[ID_SELF]
14178 PUSH EAX
14179 CALL SetProp
14181 XOR EAX, EAX
14182 MOV [CreatingWindow], EAX
14183 POP EAX // EAX = self_
14184 JMP @@self_got
14186 @@get_self_prop:
14187 PUSH Offset[ID_SELF]
14188 PUSH EAX
14189 CALL GetProp
14190 TEST EAX, EAX
14191 JNZ @@self_got
14193 @@self_is_nil:
14194 OR EAX, [ Applet ]
14195 JNZ @@self_got
14197 //try_defwndproc:
14198 POP EDI
14199 POP ESI
14200 MOV ESP, EBP
14201 POP EBP
14202 JMP DefWindowProc
14204 //@@id_self:
14205 // DB 'SELF_',0
14207 @@self_got:
14208 MOV EDX, EDI
14209 //CALL TControl.WndProc
14210 CALL CallCtlWndProc
14212 POP EDI
14213 POP ESI
14215 MOV ESP, EBP
14216 end;
14217 {$ELSE ASM_VERSION} //Pascal
14218 function WndFunc( W: HWnd; Msg: Cardinal; wParam, lParam: Integer )
14219 : Integer; stdcall;
14220 var M: TMsg;
14221 self_: PControl;
14222 begin
14223 M.hwnd := W;
14224 M.message := Msg;
14225 M.wParam := wParam;
14226 M.lParam := lParam;
14228 {$IFDEF DEBUG_ENDSESSION}
14229 if EndSession_Initiated then
14230 begin
14231 LogFileOutput( GetStartDir + 'es_debug.txt',
14232 'HWND:' + Int2Str( W ) + ' MSG:$' + Int2Hex( Msg, 4 ) +
14233 ' WParam: ' + Int2Str( wParam ) + '($' + Int2Hex( wParam, 8 ) + ')' +
14234 ' LParam: ' + Int2Str( lParam ) + '($' + Int2Hex( lParam, 8 ) + ')' );
14235 end;
14236 {$ENDIF}
14238 self_ := nil;
14239 if W <> 0 then
14240 begin
14241 if CreatingWindow <> nil then
14242 begin
14243 {$IFDEF DEBUG_CREATEWINDOW}
14244 LogFileOutput( GetStartDir + 'Session.log',
14245 'WndFunc: Creating window = ' + Int2Hex( Integer( CreatingWindow ), 4 ) +
14246 ' hwnd=' + Int2Str( M.hwnd ) +
14247 ' message=' + Int2Hex( M.message, 4 ) +
14248 ' wParam=' + Int2Str( M.wParam ) + '=$' + Int2Hex( M.wParam, 4 ) +
14249 ' lParam=' + Int2Str( M.lParam ) + '=$' + Int2Hex( M.lParam, 4 )
14251 {$ENDIF DEBUG_CREATEWINDOW}
14252 self_ := CreatingWindow;
14253 CreatingWindow.fHandle := W;
14254 SetProp( W, ID_SELF, THandle( CreatingWindow ) );
14255 CreatingWindow := nil;
14257 else
14258 self_ := Pointer( GetProp( W, ID_SELF ) );
14259 end;
14261 if self_ <> nil then
14262 Result := self_.WndProc( M )
14263 else
14264 if Assigned( Applet ) then
14265 Result := Applet.WndProc( M )
14266 else
14267 Result := DefWindowProc( W, Msg, wParam, lParam );
14268 {$IFDEF DEBUG_ENDSESSION}
14269 if EndSession_Initiated then
14270 begin
14271 LogFileOutput( GetStartDir + 'es_debug.txt',
14272 'HWND:' + Int2Str( W ) + ' MSG:$' + Int2Hex( Msg, 4 ) +
14273 ' Result: ' + Int2Str( Result ) + '($' + Int2Hex( Result, 8 ) + ')' );
14274 end;
14275 {$ENDIF}
14276 end;
14277 //[END WndFunc]
14278 {$ENDIF ASM_VERSION}
14281 IdleHandlers: PList;
14282 ProcessIdle: procedure ( Sender: PObj ) = DummyObjProc;
14284 //[procedure ProcessIdleProc]
14285 procedure ProcessIdleProc( Sender: PObj );
14287 i: integer;
14288 m: TMethod;
14289 begin
14290 if AppletTerminated then exit; // YS +
14291 i := 0;
14292 with IdleHandlers{-}^{+} do
14293 while i < Count do begin
14294 m.Code:=Items[i];
14295 Inc(i);
14296 m.Data:=Items[i];
14297 Inc(i);
14298 TOnEvent(m)(Sender);
14299 end;
14300 end;
14302 //[function FindIdleHandler]
14303 function FindIdleHandler( const OnIdle: TOnEvent ): integer;
14305 i: integer;
14306 begin
14307 i := 0;
14308 if not AppletTerminated then //+ {Maxim Pushkar}
14309 with TMethod(OnIdle), IdleHandlers{-}^{+} do
14310 while i < Count do begin
14311 if (Items[i] = Code) and (Items[i + 1] = Data) then
14312 begin
14313 Result := i;
14314 exit;
14315 end;
14316 Inc(i, 2);
14317 end;
14318 Result := -1;
14319 end;
14320 //[END FindIdleHandler]
14322 //[procedure RegisterIdleHandler]
14323 procedure RegisterIdleHandler( const OnIdle: TOnEvent );
14324 begin
14325 if IdleHandlers = nil then begin
14326 IdleHandlers := NewList;
14327 if Applet <> nil then
14328 Applet.Add2AutoFree(IdleHandlers);
14329 end;
14330 with TMethod(OnIdle) do
14331 begin
14332 IdleHandlers.Add(Code);
14333 IdleHandlers.Add(Data);
14334 end;
14335 ProcessIdle := @ProcessIdleProc;
14336 end;
14338 //[procedure UnRegisterIdleHandler]
14339 procedure UnRegisterIdleHandler( const OnIdle: TOnEvent );
14341 i: integer;
14342 begin
14343 i := FindIdleHandler(OnIdle);
14344 if i <> -1 then
14345 with IdleHandlers{-}^{+} do
14346 begin
14347 Delete(i);
14348 Delete(i);
14349 end;
14350 end;
14352 //[procedure TerminateExecution]
14353 procedure TerminateExecution( var AppletWnd: PControl );
14354 var App: PControl;
14355 Appalreadyterminated: Boolean;
14356 begin
14357 Appalreadyterminated := AppletTerminated;
14358 AppletTerminated := TRUE;
14359 AppletRunning := FALSE;
14360 App := Applet;
14361 Applet := nil;
14362 if (App <> nil) {and (App.RefCount >= 0)} then
14363 begin
14364 App.RefInc;
14365 if not Appalreadyterminated then
14366 begin
14367 App.ProcessMessages;
14368 App.Perform( WM_CLOSE, 0, 0 );
14369 end;
14370 AppletWnd := nil;
14371 App.Free;
14372 App.RefDec;
14373 end;
14374 end;
14376 //[PROCEDURE CallTControlCreateWindow]
14377 {$IFDEF ASM_VERSION}
14378 procedure CallTControlCreateWindow( Ctl: PControl );
14379 begin
14380 Ctl.CreateWindow;
14381 end;
14382 //[END CallTControlCreateWindow]
14384 //[PROCEDURE Run]
14385 procedure Run( var AppletWnd: PControl );
14387 PUSH EBX
14388 XCHG EBX, EAX
14390 INC [AppletRunning]
14391 MOV EAX, [EBX]
14392 MOV [Applet], EAX
14393 CALL CallTControlCreateWindow
14394 JMP @@2
14395 @@1:
14396 CALL WaitMessage
14397 MOV EAX, [EBX]
14398 CALL TControl.ProcessMessages
14399 {$IFNDEF NOT_USE_OnIdle}
14400 MOV EAX, [EBX]
14401 CALL [ProcessIdle]
14402 {$ENDIF}
14403 @@2:
14404 CMP [AppletTerminated],0
14405 JZ @@1
14407 XCHG EAX, EBX
14409 POP EBX
14410 TEST EAX, EAX
14411 JNZ TerminateExecution
14412 end;
14413 {$ELSE ASM_VERSION} //Pascal
14414 procedure Run( var AppletWnd: PControl );
14415 begin
14416 AppletRunning := True;
14417 Applet := AppletWnd;
14418 AppletWnd.CreateWindow; //virtual!!!
14419 while not AppletTerminated do
14420 begin
14421 WaitMessage;
14422 AppletWnd.ProcessMessages;
14423 {$IFNDEF NOT_USE_OnIdle}
14424 ProcessIdle( AppletWnd );
14425 {$ENDIF}
14426 end;
14427 if AppletWnd <> nil then
14428 TerminateExecution( AppletWnd );
14429 end;
14430 //[END Run]
14431 {$ENDIF ASM_VERSION}
14433 //[procedure AppletMinimize]
14434 procedure AppletMinimize;
14435 begin
14436 if Applet = nil then Exit;
14437 Applet.Perform( WM_SYSCOMMAND, SC_MINIMIZE, 0 );
14438 end;
14440 //[procedure AppletHide]
14441 procedure AppletHide;
14442 begin
14443 if Applet = nil then Exit;
14444 AppletMinimize;
14445 Applet.Hide;
14446 end;
14448 //[procedure AppletRestore]
14449 procedure AppletRestore;
14450 begin
14451 if Applet = nil then Exit;
14452 Applet.Show;
14453 Applet.Perform( WM_SYSCOMMAND, SC_RESTORE, 0 );
14454 end;
14456 //[function ScreenWidth]
14457 function ScreenWidth: Integer;
14458 begin
14459 Result := GetSystemMetrics( SM_CXSCREEN );
14460 end;
14461 //[END ScreenWidth]
14463 //[function ScreenHeight]
14464 function ScreenHeight: Integer;
14465 begin
14466 Result := GetSystemMetrics( SM_CYSCREEN );
14467 end;
14468 //[END ScreenHeight]
14476 {$IFDEF USE_CONSTRUCTORS}
14477 {$DEFINE WNDPROCAPP_USED}
14478 {$DEFINE WNDPROCAPP_ASM_USED}
14479 {$ENDIF USE_CONSTRUCTORS}
14480 {$IFNDEF ASM_VERSION}
14481 {$DEFINE WNDPROCAPP_USED}
14482 {$ENDIF ASM_VERSION}
14484 {$DEFINE WNDPROCAPP_USED}
14488 {$IFNDEF WNDPROCAPP_USED}
14489 //[WndProcXXX FORWARD DECLARATIONS]
14490 {$IFNDEF ASM_VERSION}
14491 function WndProcApp( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14492 {$ENDIF}
14493 {$ENDIF}
14494 function WndProcForm( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14495 //function WndProcCtrl( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14496 function WndProcPaint( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14497 function WndProcGradient( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14498 function WndProcGradientEx( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14499 function WndProcLabelEffect( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14500 //function WndProcParentResize(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14501 //function WndProcResize(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14502 function WndProcNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14503 function WndProcCommonNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14504 var fGlobalProcKeybd: function( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean =
14505 WndProcDummy;
14506 //[END OF WndProcXXX FORWARD DECLARATIONS]
14520 { -- Graphics support -- }
14522 //[function _NewGraphicTool]
14523 function _NewGraphicTool: PGraphicTool;
14524 begin
14526 New( Result, Create );
14528 {++}(*Result := PGraphicTool.Create;*){--}
14529 end;
14530 //[END _NewGraphicTool]
14532 //[FUNCTION SimpleGetCtlBrushHandle]
14533 {$IFDEF ASM_VERSION}
14534 function SimpleGetCtlBrushHandle( Sender: PControl ): HBrush;
14535 asm // //
14536 @@1: MOV ECX, [EAX].TControl.fParent
14537 JECXZ @@2
14538 MOV EDX, [EAX].TControl.fColor
14539 CMP EDX, [ECX].TControl.fColor
14540 XCHG EAX, ECX
14541 JE @@1
14542 XCHG EAX, ECX
14543 @@2: PUSH EBX
14544 XCHG EBX, EAX
14545 MOV ECX, [EBX].TControl.fTmpBrush
14546 JECXZ @@3
14547 MOV EAX, [EBX].TControl.fColor
14548 CALL Color2RGB
14549 CMP EAX, [EBX].TControl.fTmpBrushColorRGB
14550 JE @@3
14551 XOR EAX, EAX
14552 XCHG [EBX].TControl.fTmpBrush, EAX
14553 PUSH EAX
14554 CALL DeleteObject
14555 @@3: MOV EAX, [EBX].TControl.fTmpBrush
14556 TEST EAX, EAX
14557 JNE @@4
14558 MOV EAX, [EBX].TControl.fColor
14559 CALL Color2RGB
14560 MOV [EBX].TControl.fTmpBrushColorRGB, EAX
14561 PUSH EAX
14562 CALL CreateSolidBrush
14563 MOV [EBX].TControl.fTmpBrush, EAX
14564 @@4: POP EBX
14565 end;
14566 {$ELSE ASM_VERSION PAS_VERSION}
14567 function SimpleGetCtlBrushHandle( Sender: PControl ): HBrush;
14568 begin
14569 if (Sender.fParent <> nil) and (Sender.fColor = Sender.fParent.fColor) then
14570 Result := SimpleGetCtlBrushHandle( Sender.fParent )
14571 else
14572 begin
14573 if (Sender.fTmpBrush <> 0) and
14574 (Color2RGB( Sender.fColor ) <> Sender.fTmpBrushColorRGB) then
14575 begin
14576 DeleteObject( Sender.fTmpBrush );
14577 Sender.fTmpBrush := 0;
14578 end;
14579 if Sender.fTmpBrush = 0 then
14580 begin
14581 Sender.fTmpBrushColorRGB := Color2RGB( Sender.fColor );
14582 Sender.fTmpBrush := CreateSolidBrush( Sender.fTmpBrushColorRGB );
14583 end;
14584 Result := Sender.fTmpBrush;
14585 end;
14586 end;
14587 {$ENDIF ASM_VERSION}
14588 //[END SimpleGetCtlBrushHandle]
14590 //[function NormalGetCtlBrushHandle]
14591 function NormalGetCtlBrushHandle( Sender: PControl ): HBrush;
14592 begin
14593 if (Sender.fParent <> nil) then
14594 Sender.Brush.fParentGDITool := Sender.fParent.Brush;
14595 {if (Sender.Brush.fHandle <> 0) and
14596 (Color2RGB( Sender.fBrush.fData.Color ) <> Sender.fBrush.fColorRGB) then
14597 DeleteObject( Sender.Brush.ReleaseHandle );}
14598 Result := Sender.Brush.Handle;
14599 end;
14600 //[END NormalGetCtlBrushHandle]
14602 {++}(*
14603 //[API CreateFontIndirect]
14604 function CreateFontIndirect(const p1: TLogFont): HFONT; stdcall;
14605 external gdi32 name 'CreateFontIndirectA';
14606 *){--}
14607 //[MakeXXXHandle FORWARD DECLARATIONS]
14608 function MakeFontHandle( Self_: PGraphicTool ): THandle; forward;
14609 function MakeBrushHandle( Self_: PGraphicTool ): THandle; forward;
14610 function MakePenHandle( Self_: PGraphicTool ): THandle; forward;
14611 function MakeGeometricPenHandle( Self_: PGraphicTool ): THandle; forward;
14612 //[END OF MakeXXXHandle FORWARD DECLARATIONS]
14614 //[FUNCTION NewBrush]
14615 {$IFDEF ASM_VERSION}
14616 function NewBrush: PGraphicTool;
14618 MOV [Global_GetCtlBrushHandle], offset NormalGetCtlBrushHandle
14619 CALL _NewGraphicTool
14620 MOV [EAX].TGraphicTool.fNewProc, offset[NewBrush]
14621 MOV [EAX].TGraphicTool.fType, gttBrush
14622 MOV [EAX].TGraphicTool.fMakeHandleProc, offset[MakeBrushHandle]
14623 MOV [EAX].TGraphicTool.fData.Color, clBtnFace
14624 end;
14625 {$ELSE ASM_VERSION} //Pascal
14626 function NewBrush: PGraphicTool;
14627 begin
14628 Global_GetCtlBrushHandle := NormalGetCtlBrushHandle;
14629 Result := _NewGraphicTool;
14630 with Result {-}^{+} do
14631 begin
14632 fNewProc := @ NewBrush;
14633 fType := gttBrush;
14634 fMakeHandleProc := @ MakeBrushHandle;
14635 Result.fData.Color := clBtnFace;
14636 //Result.fData.Brush.Style := bsSolid;
14637 end;
14638 end;
14639 {$ENDIF ASM_VERSION}
14640 //[END NewBrush]
14642 const size_FontData = sizeof( Integer {fFontHeight} ) + sizeof( Integer {fFontWidth} ) +
14643 sizeof( TFontPitch ) + sizeof( TFontStyle ) +
14644 sizeof( Integer {fFontOrientation} ) +
14645 sizeof( Integer {fFontWeight} ) + sizeof( TFontCharset ) +
14646 sizeof( TFontQuality );
14648 //[FUNCTION NewFont]
14649 {$IFDEF ASM_VERSION}
14650 function NewFont: PGraphicTool;
14651 const FontDtSz = sizeof( TGDIFont );
14653 CALL _NewGraphicTool
14654 MOV [EAX].TGraphicTool.fNewProc, offset[NewFont]
14655 MOV [EAX].TGraphicTool.fType, gttFont
14656 MOV [EAX].TGraphicTool.fMakeHandleProc, offset[MakeFontHandle]
14657 MOV EDX, [DefFontColor]
14658 MOV [EAX].TGraphicTool.fData.Color, EDX
14660 PUSH EAX
14661 LEA EDX, [EAX].TGraphicTool.fData.Font
14662 MOV EAX, offset[ DefFont ]
14663 XOR ECX, ECX
14664 MOV CL, FontDtSz
14665 CALL System.Move
14666 POP EAX
14667 end;
14668 {$ELSE ASM_VERSION} //Pascal
14669 function NewFont: PGraphicTool;
14670 begin
14671 Result := _NewGraphicTool;
14672 with Result {-}^{+} do
14673 begin
14674 fNewProc := @ NewFont;
14675 fType := gttFont;
14676 fMakeHandleProc := @ MakeFontHandle;
14677 fData.Color := DefFontColor;
14678 Move( DefFont, fData.Font, Sizeof( TGDIFont ) );
14679 end;
14680 end;
14681 {$ENDIF ASM_VERSION}
14682 //[END NewFont]
14684 //[FUNCTION NewPen]
14685 {$IFDEF ASM_VERSION}
14686 function NewPen: PGraphicTool;
14688 CALL _NewGraphicTool
14689 MOV [EAX].TGraphicTool.fNewProc, offset[NewPen]
14690 MOV [EAX].TGraphicTool.fType, gttPen
14691 MOV [EAX].TGraphicTool.fMakeHandleProc, offset[MakePenHandle]
14692 MOV [EAX].TGraphicTool.fData.Pen.Mode, pmCopy
14693 end;
14694 {$ELSE ASM_VERSION} //Pascal
14695 function NewPen: PGraphicTool;
14696 begin
14697 Result := _NewGraphicTool;
14698 with Result{-}^{+} do
14699 begin
14700 fNewProc := @ NewPen;
14701 fType := gttPen;
14702 fMakeHandleProc := @ MakePenHandle;
14703 fData.Pen.Mode := pmCopy;
14704 end;
14705 end;
14706 {$ENDIF ASM_VERSION}
14707 //[END NewPen]
14710 //[function Color2RGB]
14711 function Color2RGB( Color: TColor ): TColor;
14712 begin
14713 if Color < 0 then
14714 Result := GetSysColor(Color and $FF) else
14715 Result := Color;
14716 end;
14717 //[END Color2RGB]
14719 //[function ColorsMix]
14720 function ColorsMix( Color1, Color2: TColor ): TColor;
14721 {$IFDEF F_P}
14722 begin
14723 Result := ((Color2RGB( Color1 ) and $FEFEFE) shr 1) +
14724 ((Color2RGB( Color2 ) and $FEFEFE) shr 1);
14725 end;
14726 {$ELSE DELPHI}
14728 PUSH EDX
14729 CALL Color2Rgb
14730 XCHG EAX, [ESP]
14731 CALL Color2Rgb
14732 POP EDX
14733 AND EAX, 0FEFEFEh
14734 AND EDX, 0FEFEFEh
14735 SHR EAX, 1
14736 SHR EDX, 1
14737 ADD EAX, EDX
14738 end;
14739 {$ENDIF F_P/DELPHI}
14740 //[END ColorsMix]
14742 //[FUNCTION Color2RGBQuad]
14743 {$IFDEF ASM_VERSION}
14744 function Color2RGBQuad( Color: TColor ): TRGBQuad;
14746 CALL Color2RGB
14747 // code by bart:
14748 xchg ah,al // xxRRGGBB
14749 ror eax,16 // BBGGxxRR
14750 xchg ah,al // BBGGRRxx
14751 shr eax,8 // 00BBGGRR
14752 end;
14753 {$ELSE ASM_VERSION} //Pascal
14754 function Color2RGBQuad( Color: TColor ): TRGBQuad;
14755 var C: Integer;
14756 begin
14757 C := Color2RGB( Color );
14758 C := ((C shr 16) and $FF)
14759 or ((C shl 16) and $FF0000)
14760 or (C and $FF00);
14761 Result := TRGBQuad( C );
14762 end;
14763 {$ENDIF ASM_VERSION}
14764 //[END Color2RGBQuad]
14766 //[FUNCTION Color2Color16]
14767 {$IFDEF ASM_VERSION}
14768 function Color2Color16( Color: TColor ): WORD;
14770 MOV EDX, EAX
14771 SHR EDX, 19
14772 AND EDX, $1F
14773 MOV ECX, EAX
14774 SHR ECX, 5
14775 AND ECX, $7E0;
14776 MOV AH, AL
14777 AND EAX, $F800
14778 OR EAX, EDX
14779 OR EAX, ECX
14780 end;
14781 {$ELSE ASM_VERSION}
14782 function Color2Color16( Color: TColor ): WORD;
14783 begin
14784 Color := Color2RGB( Color );
14785 Result := (Color shr 19) and $1F or
14786 (Color shr 5) and $7E0 or
14787 (Color shl 8) and $F800;
14788 end;
14789 {$ENDIF ASM_VERSION}
14790 //[END Color2Color16]
14792 { TGraphicTool }
14794 {$IFDEF ASM_VERSION}
14795 //[function TGraphicTool.Assign]
14796 function TGraphicTool.Assign(Value: PGraphicTool): PGraphicTool;
14797 const SzfData = sizeof( fData );
14798 asm // //
14799 TEST EDX, EDX
14800 JNZ @@1
14801 TEST EAX, EAX
14802 JZ @@0
14803 CALL TObj.DoDestroy
14804 XOR EAX, EAX
14805 @@0: RET
14806 @@1: PUSH EDI
14807 MOV EDI, EDX
14808 TEST EAX, EAX
14809 JNZ @@2
14810 XCHG EAX, EDX
14811 CALL dword ptr[EAX].TGraphicTool.fNewProc
14812 @@2: CMP EAX, EDI
14813 JE @@exit
14814 PUSH EBX
14815 XCHG EBX, EAX
14817 MOV ECX, [EBX].TGraphicTool.fHandle
14818 JECXZ @@3
14819 CMP ECX, [EDI].TGraphicTool.fHandle
14820 JE @@exit1
14821 @@3:
14822 MOV EAX, EBX
14823 CALL TGraphicTool.Changed
14824 LEA EDX, [EBX].TGraphicTool.fData
14825 LEA EAX, [EDI].TGraphicTool.fData
14826 MOV ECX, SzfData
14827 CALL System.Move
14828 MOV EAX, EBX
14829 CALL TGraphicTool.Changed
14831 @@exit1:
14832 XCHG EAX, EBX
14833 POP EBX
14834 @@exit: POP EDI
14835 end;
14836 {$ELSE ASM_VERSION}
14837 function TGraphicTool.Assign(Value: PGraphicTool): PGraphicTool;
14838 var _Self: PGraphicTool;
14839 begin
14840 Result := nil;
14841 if Value = nil then
14842 begin
14843 if @Self <> nil then
14844 DoDestroy;
14845 Exit;
14846 end;
14847 _Self := @Self;
14848 if _Self = nil then
14849 _Self := Value.fNewProc();
14850 Result := _Self;
14851 if _Self = Value then Exit; // to avoid infinite loop when assigning to itself
14852 if _Self.fHandle <> 0 then
14853 if Value.fHandle = _Self.fHandle then Exit;
14854 _Self.Changed; // to destroy handle if allocated and release it from the canvas (if any uses it)
14855 Assert( Value.fType = _Self.fType, 'Attempt to assign to different GDI tool type' );
14856 Move( Value.fData, _Self.fData, Sizeof( fData ) );
14857 _Self.Changed; // to inform owner control, that its tool (font, brush) changed
14858 end;
14859 {$ENDIF ASM_VERSION}
14861 //[procedure TGraphicTool.AssignHandle]
14862 procedure TGraphicTool.AssignHandle(NewHandle: Integer);
14863 begin
14864 //------------ by Yury Sidorov --------
14865 //Changed;
14866 //-------------------------------------//
14867 if fHandle <> 0 then //
14868 DeleteObject( fHandle ); //
14869 //-------------------------------------//
14870 fHandle := NewHandle;
14871 GetObject( fHandle, Sizeof( TGDIFont ), @ fData.Font );
14872 Changed;
14873 end;
14875 {$IFDEF ASM_VERSION}
14876 //[procedure TGraphicTool.Changed]
14877 procedure TGraphicTool.Changed;
14879 XOR ECX, ECX
14880 XCHG ECX, [EAX].fHandle
14881 JECXZ @@exit
14882 PUSH EAX
14883 PUSH ECX
14885 CALL @@CallOnChange
14887 CALL DeleteObject
14888 POP EAX
14889 @@exit:
14891 @@CallOnChange:
14892 MOV ECX, [EAX].fOnChange.TMethod.Code
14893 JECXZ @@no_onChange
14894 PUSH EAX
14895 XCHG EDX, EAX
14896 MOV EAX, [EDX].fOnChange.TMethod.Data
14897 CALL ECX
14898 POP EAX
14899 @@no_onChange:
14900 end;
14901 {$ELSE ASM_VERSION} //Pascal
14902 procedure TGraphicTool.Changed;
14903 var H: THandle;
14904 begin
14905 if fHandle <> 0 then
14906 begin
14907 H := fHandle;
14908 fHandle := 0;
14909 ////////////////////////////////
14910 if Assigned( fOnChange ) then
14911 fOnChange( @Self );
14912 ////////////////////////////////
14913 DeleteObject( H );
14914 {$IFDEF DEBUG_GDIOBJECTS}
14915 case fType of
14916 gttBrush: Dec( BrushCount );
14917 gttFont: Dec( FontCount );
14918 gttPen: Dec( PenCount );
14919 end;
14920 {$ENDIF}
14921 end;
14922 //////////////////////////////////
14923 if Assigned( fOnChange ) then
14924 fOnChange( @Self );
14925 //////////////////////////////////
14926 end;
14927 {$ENDIF ASM_VERSION}
14929 {$IFDEF ASM_VERSION}
14930 //[destructor TGraphicTool.Destroy]
14931 destructor TGraphicTool.Destroy;
14933 PUSH EAX
14934 CMP [EAX].fType, gttFont
14935 JE @@0
14936 MOV ECX, [EAX].fData.Brush.Bitmap
14937 JECXZ @@0
14938 PUSH ECX
14939 CALL DeleteObject
14940 POP EAX
14941 PUSH EAX
14942 @@0:
14943 MOV ECX, [EAX].fHandle
14944 JECXZ @@1
14945 PUSH ECX
14946 CALL DeleteObject
14947 @@1:
14948 POP EAX
14949 CALL TObj.Destroy
14950 end;
14951 {$ELSE ASM_VERSION} //Pascal
14952 destructor TGraphicTool.Destroy;
14953 begin
14954 case fType of
14955 gttBrush: if fData.Brush.Bitmap <> 0 then
14956 DeleteObject( fData.Brush.Bitmap );
14957 gttPen: if fData.Pen.BrushBitmap <> 0 then
14958 DeleteObject( fData.Pen.BrushBitmap )
14959 end;
14960 if fHandle <> 0 then
14961 begin
14962 DeleteObject( fHandle );
14963 {$IFDEF DEBUG_GDIOBJECTS}
14964 case fType of
14965 gttPen: Dec( PenCount );
14966 gttBrush: Dec( BrushCount );
14967 gttFont: Dec( FontCount );
14968 end;
14969 {$ENDIF}
14970 //fHandle := 0; Why to do this? It is now destroying!
14971 end;
14972 inherited;
14973 end;
14974 {$ENDIF ASM_VERSION}
14976 //[function TGraphicTool.HandleAllocated]
14977 function TGraphicTool.HandleAllocated: Boolean;
14978 begin
14979 Result := fHandle <> 0;
14980 end;
14982 {$IFDEF ASM_VERSION}
14983 //[function TGraphicTool.ReleaseHandle]
14984 function TGraphicTool.ReleaseHandle: Integer;
14985 asm // //
14986 PUSH EAX
14987 CALL Changed
14988 POP EDX
14989 XOR EAX, EAX
14990 XCHG [EDX].fHandle, EAX
14991 end;
14992 {$ELSE ASM_VERSION PAS_VERSION}
14993 function TGraphicTool.ReleaseHandle: Integer;
14994 begin
14995 Changed;
14996 Result := fHandle;
14997 fHandle := 0;
14998 end;
14999 {$ENDIF ASM_VERSION}
15001 {$IFDEF ASM_VERSION}
15002 //[procedure TGraphicTool.SetInt]
15003 procedure TGraphicTool.SetInt( const Index: Integer; Value: Integer );
15005 LEA EDX, [EDX+EAX].fData
15006 CMP [EDX], ECX
15007 JE @@exit
15008 MOV [EDX], ECX
15009 CALL Changed
15010 @@exit:
15011 end;
15012 {$ELSE ASM_VERSION} //Pascal
15013 procedure TGraphicTool.SetInt( const Index: Integer; Value: Integer );
15014 var Where: PInteger;
15015 begin
15016 Where := Pointer( Integer( @ fData ) + Index );
15017 if Where^ = Value then Exit;
15018 Where^ := Value;
15019 Changed;
15020 end;
15021 {$ENDIF ASM_VERSION}
15023 {$IFDEF F_P}
15024 //[function TGraphicTool.GetInt]
15025 function TGraphicTool.GetInt(const Index: Integer): Integer;
15026 var Where: PInteger;
15027 begin
15028 Where := Pointer( Integer( @ fData ) + Index );
15029 Result := Where^;
15030 end;
15031 {$ENDIF}
15033 //[procedure TGraphicTool.SetColor]
15034 procedure TGraphicTool.SetColor( Value: TColor );
15035 begin
15036 SetInt( go_Color, Value );
15037 fColorRGB := Color2RGB( Value );
15038 end;
15040 {$IFDEF ASM_VERSION}
15041 //[function TGraphicTool.IsFontTrueType]
15042 function TGraphicTool.IsFontTrueType: Boolean;
15044 CALL GetHandle
15045 TEST EAX, EAX
15046 JZ @@exit
15048 PUSH EBX
15050 PUSH EAX // fHandle
15052 PUSH 0
15053 CALL GetDC
15055 PUSH EAX // DC
15056 MOV EBX, EAX
15057 CALL SelectObject
15058 PUSH EAX
15060 XOR ECX, ECX
15061 PUSH ECX
15062 PUSH ECX
15063 PUSH ECX
15064 PUSH ECX
15065 PUSH EBX
15066 CALL GetFontData
15068 XCHG EAX, [ESP]
15070 PUSH EAX
15071 PUSH EBX
15072 CALL SelectObject
15074 PUSH EBX
15075 PUSH 0
15076 CALL ReleaseDC
15078 POP EAX
15079 INC EAX
15080 SETNZ AL
15082 POP EBX
15083 @@exit:
15084 end;
15085 {$ELSE ASM_VERSION} //Pascal
15086 function TGraphicTool.IsFontTrueType: Boolean;
15087 var OldFont: HFont;
15088 DC: HDC;
15089 begin
15090 Result := False;
15091 if GetHandle = 0 then Exit;
15092 DC := GetDC( 0 );
15093 OldFont := SelectObject( DC, fHandle );
15094 if GetFontData( DC, 0, 0, nil, 0 ) <> GDI_ERROR then
15095 Result := True;
15096 SelectObject( DC, OldFont );
15097 ReleaseDC( 0, DC );
15098 end;
15099 {$ENDIF ASM_VERSION}
15101 //[procedure TGraphicTool.SetBrushBitmap]
15102 procedure TGraphicTool.SetBrushBitmap(const Value: HBitmap);
15103 begin
15104 if fData.Brush.Bitmap = Value then Exit;
15105 if fData.Brush.Bitmap <> 0 then
15106 begin
15107 ///////////
15108 Changed; // !!!
15109 ///////////
15110 DeleteObject( fData.Brush.Bitmap );
15111 end;
15112 fData.Brush.Bitmap := Value;
15113 Changed;
15114 end;
15116 //[procedure TGraphicTool.SetBrushStyle]
15117 procedure TGraphicTool.SetBrushStyle(const Value: TBrushStyle);
15118 begin
15119 if fData.Brush.Style = Value then Exit;
15120 fData.Brush.Style := Value;
15121 Changed;
15122 end;
15124 //[procedure TGraphicTool.SetFontCharset]
15125 procedure TGraphicTool.SetFontCharset(const Value: TFontCharset);
15126 begin
15127 if fData.Font.Charset = Value then Exit;
15128 fData.Font.Charset := Value;
15129 Changed;
15130 end;
15132 //[procedure TGraphicTool.SetFontQuality]
15133 procedure TGraphicTool.SetFontQuality(const Value: TFontQuality);
15134 begin
15135 if fData.Font.Quality = Value then Exit;
15136 fData.Font.Quality := Value;
15137 Changed;
15138 end;
15140 //[function TGraphicTool.GetFontName]
15141 function TGraphicTool.GetFontName: String;
15142 begin
15143 Result := fData.Font.Name;
15144 end;
15146 //[procedure TGraphicTool.SetFontName]
15147 procedure TGraphicTool.SetFontName(const Value: String);
15148 begin
15149 if fData.Font.Name = Value then Exit;
15150 FillChar( fData.Font.Name[ 0 ], LF_FACESIZE, 0 );
15151 StrLCopy( fData.Font.Name, PChar( Value ), LF_FACESIZE );
15152 Changed;
15153 end;
15155 {$IFDEF ASM_VERSION}
15156 //[procedure TextAreaEx]
15157 procedure TextAreaEx( Sender: PCanvas; var Sz : TSize; var Pt : TPoint );
15159 PUSH EBX
15160 PUSH ESI
15161 PUSH EDI
15162 PUSH EBP
15163 MOV EBP, ESP
15164 PUSH EDX // [EBP-4] = @Sz
15165 PUSH ECX // [EBP-8] = @Pt
15166 MOV EBX, EAX
15167 CALL TCanvas.GetFont
15168 MOV ESI, [EAX].TGraphicTool.fData.Font.Orientation
15169 CALL TGraphicTool.IsFontTrueType
15170 TEST AL, AL
15171 JZ @@exit
15173 MOV EDI, [EBP-8]
15174 XOR EAX, EAX
15175 STOSD
15176 STOSD
15177 TEST ESI, ESI
15178 JZ @@exit
15180 PUSH EAX // Pts[1].x
15181 PUSH EAX // Pts[1].y
15183 PUSH ESI
15184 FILD dword ptr [ESP]
15185 POP EDX
15187 FILD word ptr [@@1800]
15188 FDIV
15189 //FWAIT
15190 FLDPI
15191 FMUL
15192 //FWAIT
15194 FLD ST(0)
15195 FSINCOS
15196 FWAIT
15198 MOV ESI, [EBP-4]
15199 LODSD // Sz.cx
15200 PUSH EAX
15201 FILD dword ptr [ESP]
15202 FMUL
15203 FISTP dword ptr [ESP] // Pts[2].x
15204 FWAIT
15205 NEG EAX
15206 PUSH EAX
15207 FILD dword ptr [ESP]
15208 FMUL
15209 FISTP dword ptr [ESP] // Pts[2].y
15210 FWAIT
15212 FLDPI
15213 FLD1
15214 FLD1
15215 FADD
15216 FDIV
15217 FADD
15218 FSINCOS
15219 FWAIT
15221 LODSD
15222 NEG EAX
15223 PUSH EAX
15224 FILD dword ptr [ESP]
15225 FMUL
15226 FISTP dword ptr [ESP] // Pts[4].x
15227 FWAIT
15228 NEG EAX
15229 PUSH EAX
15230 FILD dword ptr [ESP]
15231 FMUL
15232 FISTP dword ptr [ESP] // Pts[4].y
15233 FWAIT
15235 POP ECX
15236 POP EDX
15237 PUSH EDX
15238 PUSH ECX
15239 ADD EDX, [ESP+12]
15240 ADD ECX, [ESP+8]
15241 PUSH EDX
15242 PUSH ECX
15244 MOV ESI, ESP
15245 XOR EDX, EDX // MinX
15246 XOR EDI, EDI // MinY
15247 XOR ECX, ECX
15248 MOV CL, 3
15250 @@loo1: LODSD
15251 CMP EAX, EDI
15252 JGE @@1
15253 XCHG EDI, EAX
15254 @@1: LODSD
15255 CMP EAX, EDX
15256 JGE @@2
15257 XCHG EDX, EAX
15258 @@2: LOOP @@loo1
15260 MOV ESI, [EBP-4]
15261 MOV [ESI], ECX
15262 MOV [ESI+4], ECX
15263 MOV CL, 4
15264 @@loo2:
15265 POP EBX
15266 SUB EBX, EDI
15267 CMP EBX, [ESI+4]
15268 JLE @@3
15269 MOV [ESI+4], EBX
15270 @@3:
15271 POP EAX
15272 SUB EAX, EDX
15273 CMP EAX, [ESI]
15274 JLE @@4
15275 MOV [ESI], EAX
15276 @@4:
15277 LOOP @@loo2
15279 MOV EDI, [EBP-8]
15280 STOSD
15281 XCHG EAX, EBX
15282 STOSD
15283 JMP @@exit
15285 @@1800: DW 1800
15287 @@exit:
15288 MOV ESP, EBP
15289 POP EBP
15290 POP EDI
15291 POP ESI
15292 POP EBX
15293 end;
15294 {$ELSE ASM_VERSION} //Pascal
15295 procedure TextAreaEx( Sender: PCanvas; var Sz : TSize; var Pt : TPoint );
15296 var Orient : Integer;
15297 Pts : array[ 1..4 ] of TPoint;
15298 MinX, MinY, I : Integer;
15299 A : Double;
15300 begin
15301 if not Sender.Font.IsFontTrueType then Exit;
15302 Orient := Sender.Font.FontOrientation;
15303 Pt.x := 0; Pt.y := 0;
15304 if Orient = 0 then
15305 Exit;
15306 A := Orient / 1800.0 * PI;
15307 Pts[ 1 ] := Pt;
15308 Pts[ 2 ].x := Round( Sz.cx * cos( A ) );
15309 Pts[ 2 ].y := - Round( Sz.cx * sin( A ) );
15310 Pts[ 4 ].x := - Round( Sz.cy * cos( A + PI / 2 ) );
15311 Pts[ 4 ].y := Round( Sz.cy * sin( A + PI / 2 ) );
15312 Pts[ 3 ].x := Pts[ 2 ].x + Pts[ 4 ].x;
15313 Pts[ 3 ].y := Pts[ 2 ].y + Pts[ 4 ].y;
15314 MinX := 0; MinY := 0;
15315 for I := 2 to 4 do
15316 begin
15317 if Pts[ I ].x < MinX then
15318 MinX := Pts[ I ].x;
15319 if Pts[ I ].y < MinY then
15320 MinY := Pts[ I ].y;
15321 end;
15322 Sz.cx := 0;
15323 Sz.cy := 0;
15324 for I := 1 to 4 do
15325 begin
15326 Pts[ I ].x := Pts[ I ].x - MinX;
15327 Pts[ I ].y := Pts[ I ].y - MinY;
15328 if Pts[ I ].x > Sz.cx then
15329 Sz.cx := Pts[ I ].x;
15330 if Pts[ I ].y > Sz.cy then
15331 Sz.cy := Pts[ I ].y;
15332 end;
15333 Pt := Pts[ 1 ];
15334 end;
15335 {$ENDIF ASM_VERSION}
15337 {$IFDEF ASM_VERSION}
15338 //[procedure TGraphicTool.SetFontOrientation]
15339 procedure TGraphicTool.SetFontOrientation(Value: Integer);
15341 PUSH EAX
15342 @@1: MOV EAX, EDX
15343 MOV ECX, 3600
15345 IDIV ECX // EDX = Value mod 3600
15346 POP EAX
15348 MOV byte ptr [GlobalGraphics_UseFontOrient], 1
15349 MOV [GlobalCanvas_OnTextArea], offset[TextAreaEx]
15351 MOV [EAX].fData.Font.Escapement, EDX
15352 MOV ECX, EDX
15353 MOV DX, go_FontOrientation
15354 CALL SetInt
15355 end;
15356 {$ELSE ASM_VERSION} //Pascal
15357 procedure TGraphicTool.SetFontOrientation(Value: Integer);
15358 begin
15359 GlobalGraphics_UseFontOrient := True;
15360 GlobalCanvas_OnTextArea := TextAreaEx;
15361 Value := Value mod 3600; // -3599..+3599
15362 SetInt( go_FontOrientation, Value );
15363 SetInt( go_FontEscapement, Value );
15364 end;
15365 {$ENDIF ASM_VERSION}
15367 //[procedure TGraphicTool.SetFontPitch]
15368 procedure TGraphicTool.SetFontPitch(const Value: TFontPitch);
15369 begin
15370 if fData.Font.Pitch = Value then Exit;
15371 fData.Font.Pitch := Value;
15372 Changed;
15373 end;
15375 {$IFDEF ASM_VERSION}
15376 //[function TGraphicTool.GetFontStyle]
15377 function TGraphicTool.GetFontStyle: TFontStyle;
15379 MOV EDX, dword ptr [EAX].fData.Font.Italic
15380 AND EDX, $010101
15381 MOV EAX, [EAX].fData.Font.Weight
15382 CMP EAX, 700
15383 SETGE AL //AL:1 = fsBold
15384 ADD EDX, EDX
15385 OR EAX, EDX //AL:2 = fsItalic
15386 SHR EDX, 7
15387 OR EAX, EDX //AL:3 = fsUnderline
15388 SHR EDX, 7
15389 OR EAX, EDX //AL:4 = fsStrikeOut
15390 end;
15391 {$ELSE ASM_VERSION} //Pascal
15392 function TGraphicTool.GetFontStyle: TFontStyle;
15393 type PFontStyle = ^TFontStyle;
15394 begin
15395 Result := [ ];
15396 if fData.Font.Weight >= 700 then Result := [ fsBold ];
15397 if fData.Font.Italic then Result := Result + [ fsItalic ];
15398 if fData.Font.Underline then Result := Result + [ fsUnderline ];
15399 if fData.Font.StrikeOut then Result := Result + [ fsStrikeOut ];
15400 end;
15401 {$ENDIF ASM_VERSION}
15403 {$IFDEF ASM_VERSION}
15404 //[procedure TGraphicTool.SetFontStyle]
15405 procedure TGraphicTool.SetFontStyle(const Value: TFontStyle);
15407 PUSH EDI
15408 MOV EDI, EAX
15409 PUSH EDX
15410 CALL GetFontStyle
15411 POP EDX
15412 CMP AL, DL
15413 JE @@exit
15414 PUSH EDI
15416 LEA EDI, [EDI].fData.Font.Weight
15417 MOV ECX, [EDI]
15418 SHR EDX, 1
15419 JNC @@1
15420 CMP ECX, 700
15421 JGE @@2
15422 MOV ECX, 700
15423 JMP @@2
15424 @@1: CMP ECX, 700
15425 JL @@2
15426 XOR ECX, ECX
15427 @@2: XCHG EAX, ECX
15428 STOSD // change Weight
15429 SHR EDX, 1
15430 SETC AL
15431 STOSB // change Italic
15432 SHR EDX, 1
15433 SETC AL
15434 STOSB // change Underline
15435 SHR EDX, 1
15436 SETC AL
15437 STOSB // change StrikeOut
15438 POP EAX
15439 CALL Changed
15440 @@exit: POP EDI
15441 end;
15442 {$ELSE ASM_VERSION} //Pascal
15443 procedure TGraphicTool.SetFontStyle(const Value: TFontStyle);
15444 begin
15445 if FontStyle = Value then Exit;
15446 if fsBold in Value then
15447 begin
15448 if fData.Font.Weight < 700 then
15449 fData.Font.Weight := 700;
15451 else
15452 begin
15453 if fData.Font.Weight >= 700 then
15454 fData.Font.Weight := 0;
15455 end;
15456 fData.Font.Italic := fsItalic in Value;
15457 fData.Font.Underline := fsUnderline in Value;
15458 fData.Font.StrikeOut := fsStrikeOut in Value;
15459 Changed;
15460 end;
15461 {$ENDIF ASM_VERSION}
15463 //[procedure TGraphicTool.SetPenMode]
15464 procedure TGraphicTool.SetPenMode(const Value: TPenMode);
15465 begin
15466 if fData.Pen.Mode = Value then Exit;
15467 fData.Pen.Mode := Value;
15468 Changed;
15469 end;
15471 //[procedure TGraphicTool.SetPenStyle]
15472 procedure TGraphicTool.SetPenStyle(const Value: TPenStyle);
15473 begin
15474 if fData.Pen.Style = Value then Exit;
15475 fData.Pen.Style := Value;
15476 Changed;
15477 end;
15479 {$IFDEF ASM_VERSION}
15480 //[function TGraphicTool.GetHandle]
15481 function TGraphicTool.GetHandle: THandle;
15482 const DataSz = sizeof( TGDIToolData );
15484 PUSH EBX
15485 @@start:
15486 XCHG EBX, EAX
15487 MOV ECX, [EBX].fHandle
15488 JECXZ @@1
15490 MOV EAX, [EBX].fData.Color
15491 CALL Color2RGB
15492 CMP EAX, [EBX].fColorRGB
15493 JE @@1
15495 MOV EAX, EBX
15496 CALL ReleaseHandle
15497 PUSH EAX
15498 CALL DeleteObject
15500 @@1: MOV ECX, [EBX].fHandle
15501 INC ECX
15502 LOOP @@exit
15504 MOV ECX, [EBX].fParentGDITool
15505 JECXZ @@2
15506 LEA EDX, [ECX].fData
15507 LEA EAX, [EBX].fData
15508 MOV ECX, DataSz
15509 CALL CompareMem
15510 TEST AL, AL
15511 MOV EAX, [EBX].fParentGDITool
15512 JNZ @@start
15514 @@2: MOV ECX, [EBX].fHandle
15515 INC ECX
15516 LOOP @@exit
15518 MOV EAX, [EBX].fData.Color
15519 CALL Color2RGB
15520 MOV [EBX].fColorRGB, EAX
15521 XCHG EAX, EBX
15522 CALL dword ptr [EAX].fMakeHandleProc
15523 XCHG ECX, EAX
15525 @@exit: XCHG EAX, ECX
15526 POP EBX
15527 end;
15528 {$ELSE ASM_VERSION} //Pascal
15529 function TGraphicTool.GetHandle: THandle;
15530 begin
15531 Result := fHandle;
15532 if Result <> 0 then
15533 begin
15534 if Color2RGB( fData.Color ) <> fColorRGB then
15535 begin
15536 DeleteObject( ReleaseHandle );
15537 Result := 0;
15538 end;
15539 end;
15540 if Result = 0 then
15541 begin
15542 if Assigned( fParentGDITool ) then
15543 begin
15544 if CompareMem( @ fData, @ fParentGDITool.fData, Sizeof( fData ) ) then
15545 begin
15546 Result := fParentGDITool.Handle;
15547 Exit;
15548 end;
15549 end;
15551 if fHandle = 0 then
15552 begin
15553 fColorRGB := Color2RGB( fData.Color );
15554 fMakeHandleProc( @Self );
15555 end;
15556 Result := fHandle;
15557 end;
15558 end;
15559 {$ENDIF ASM_VERSION}
15561 //[FUNCTION MakeBrushHandle]
15562 {$IFDEF ASM_VERSION}
15563 function MakeBrushHandle( Self_: PGraphicTool ): THandle;
15565 PUSH EBX
15566 XCHG EBX, EAX
15567 MOV EAX, [EBX].TGraphicTool.fHandle
15568 TEST EAX, EAX
15569 JNZ @@exit
15571 MOV EAX, [EBX].TGraphicTool.fData.Color
15572 CALL Color2RGB // EAX = ColorRef
15574 XOR EDX, EDX
15576 MOV ECX, [EBX].TGraphicTool.fData.Brush.Bitmap
15577 PUSH ECX
15578 JECXZ @@1
15580 MOV DL, BS_PATTERN
15581 JMP @@2
15583 @@1:
15584 MOV CL, [EBX].TGraphicTool.fData.Brush.Style
15585 MOV DL, CL
15586 SUB CL, 2
15587 JL @@2
15589 XCHG ECX, [ESP]
15591 @@2: PUSH EAX
15592 PUSH EDX
15594 PUSH ESP
15595 CALL CreateBrushIndirect
15596 MOV [EBX].TGraphicTool.fHandle, EAX
15598 ADD ESP, 12
15600 @@exit:
15601 POP EBX
15602 end;
15603 {$ELSE ASM_VERSION} //Pascal
15604 function MakeBrushHandle( Self_: PGraphicTool ): THandle;
15606 LogBrush: TLogBrush;
15607 begin
15608 if Self_.fHandle = 0 then
15609 begin
15610 LogBrush.lbColor := Color2RGB( Self_.fData.Color );
15611 if Self_.fData.Brush.Bitmap <> 0 then
15612 begin
15613 LogBrush.lbStyle := BS_PATTERN;
15614 LogBrush.lbHatch := Self_.fData.Brush.Bitmap;
15616 else
15617 begin
15618 LogBrush.lbHatch := 0;
15619 case Self_.fData.Brush.Style of
15620 bsSolid: LogBrush.lbStyle := BS_SOLID;
15621 bsClear: LogBrush.lbStyle := BS_NULL;
15622 else
15623 LogBrush.lbStyle := BS_HATCHED;
15624 LogBrush.lbHatch := Ord( Self_.fData.Brush.Style ) - Ord( bsHorizontal );
15625 LogBrush.lbColor := Color2RGB( Self_.fData.Brush.LineColor );
15626 end;
15627 end;
15628 Self_.fHandle := CreateBrushIndirect(LogBrush);
15629 {$IFDEF DEBUG_GDIOBJECTS}
15630 if Self_.fHandle <> 0 then
15631 Inc( BrushCount )
15632 else
15633 ShowMessage( 'Could not create brush, error ' + Int2Str( GetLastError ) +
15634 ': ' + SysErrorMessage( GetLastError ) );
15635 {$ENDIF}
15636 end;
15637 //GlobalGraphics_OnObjectCreated( @Self );
15638 Result := Self_.fHandle;
15639 end;
15640 {$ENDIF ASM_VERSION}
15641 //[END MakeBrushHandle]
15643 //[FUNCTION MakeFontHandle]
15644 {$IFDEF ASM_VERSION}
15645 function MakeFontHandle( Self_: PGraphicTool ): THandle;
15647 XCHG EDX, EAX
15648 MOV EAX, [EDX].TGraphicTool.fHandle
15649 TEST EAX, EAX
15650 JNZ @@exit
15651 PUSH EDX
15652 LEA ECX, [EDX].TGraphicTool.fData.Font
15653 PUSH ECX
15654 CALL CreateFontIndirect
15655 POP EDX
15656 MOV [EDX].TGraphicTool.fHandle, EAX
15657 @@exit:
15658 end;
15659 {$ELSE ASM_VERSION} //Pascal
15660 function MakeFontHandle( Self_: PGraphicTool ): THandle;
15661 //var LogFont: TLogFont;
15662 begin
15663 with Self_{-}^{+} do
15664 begin
15665 if fHandle = 0 then
15666 begin
15667 fHandle := CreateFontIndirect( PLogFont( @ fData.Font )^ );
15668 {$IFDEF DEBUG_GDIOBJECTS}
15669 Inc( FontCount );
15670 {$ENDIF}
15671 end;
15672 Result := fHandle;
15673 end;
15674 end;
15675 {$ENDIF ASM_VERSION}
15676 //[END MakeFontHandle]
15678 //[FUNCTION MakePenHandle]
15679 {$IFDEF ASM_VERSION}
15680 function MakePenHandle( Self_: PGraphicTool ): THandle;
15682 PUSH EBX
15683 MOV EBX, EAX
15685 MOV EAX, [EBX].TGraphicTool.fHandle
15686 TEST EAX, EAX
15687 JNZ @@exit
15689 MOV EAX, [EBX].TGraphicTool.fData.Color
15690 CALL Color2RGB
15691 PUSH EAX
15692 PUSH EAX
15693 PUSH [EBX].TGraphicTool.fData.Pen.Width
15694 MOVZX EAX, [EBX].TGraphicTool.fData.Pen.Style
15695 PUSH EAX
15696 PUSH ESP
15697 CALL CreatePenIndirect
15698 MOV [EBX].TGraphicTool.fHandle, EAX
15699 ADD ESP, 16
15700 @@exit:
15701 POP EBX
15702 end;
15703 {$ELSE ASM_VERSION} //Pascal
15704 function MakePenHandle( Self_: PGraphicTool ): THandle;
15706 LogPen: TLogPen;
15707 begin
15708 with Self_{-}^{+} do
15709 begin
15710 //GlobalGraphics_OnObjectCreating( @Self );
15711 if fHandle = 0 then
15712 with LogPen do
15713 begin
15714 lopnStyle := Byte( fData.Pen.Style );
15715 lopnWidth.X := fData.Pen.Width;
15716 lopnColor := Color2RGB( fData.Color );
15717 fHandle := CreatePenIndirect( LogPen );
15718 {$IFDEF DEBUG_GDIOBJECTS}
15719 Inc( PenCount );
15720 {$ENDIF}
15721 end;
15722 //GlobalGraphics_OnObjectCreated( @Self );
15723 Result := fHandle;
15724 end;
15725 end;
15726 {$ENDIF ASM_VERSION}
15727 //[END MakePenHandle]
15730 //[procedure TGraphicTool.SetGeometricPen]
15731 procedure TGraphicTool.SetGeometricPen(const Value: Boolean);
15732 begin
15733 if fData.Pen.Geometric = Value then Exit;
15734 fData.Pen.Geometric := Value;
15735 fMakeHandleProc := MakeGeometricPenHandle;
15736 Changed;
15737 end;
15739 //[procedure TGraphicTool.SetPenEndCap]
15740 procedure TGraphicTool.SetPenEndCap(const Value: TPenEndCap);
15741 begin
15742 if fData.Pen.EndCap = Value then Exit;
15743 fData.Pen.EndCap := Value;
15744 Changed;
15745 end;
15747 //[procedure TGraphicTool.SetPenJoin]
15748 procedure TGraphicTool.SetPenJoin(const Value: TPenJoin);
15749 begin
15750 if fData.Pen.Join = Value then Exit;
15751 fData.Pen.Join := Value;
15752 Changed;
15753 end;
15755 //[FUNCTION MakeGeometricPenHandle]
15756 {$IFDEF ASM_VERSION}
15757 function MakeGeometricPenHandle( Self_: PGraphicTool ): THandle;
15759 MOV ECX, [EAX].TGraphicTool.fHandle
15760 INC ECX
15761 LOOP @@exit
15763 PUSH EBX
15764 XCHG EBX, EAX
15765 MOV EAX, [EBX].TGraphicTool.fData.Color
15766 CALL Color2RGB // EAX = Color2RGB( fColor )
15767 CDQ // EDX = lbHatch (0)
15768 MOV ECX, [EBX].TGraphicTool.fData.Pen.BrushBitmap
15769 JECXZ @@no_brush_bitmap
15771 XCHG EDX, ECX // lbHatch = fPenBrushBitmap
15772 MOV CL, BS_PATTERN // = 3
15773 JMP @@create_pen
15775 @@no_brush_bitmap:
15776 MOVZX ECX, [EBX].TGraphicTool.fData.Pen.BrushStyle
15777 CMP CL, 1
15778 JLE @@create_pen
15779 MOV EDX, ECX
15780 MOV CL, 2
15781 SUB EDX, ECX
15783 @@create_pen:
15784 PUSH EDX
15785 PUSH EAX
15786 PUSH ECX
15787 MOV ECX, ESP
15790 PUSH EDX
15791 PUSH EDX
15792 PUSH ECX
15793 PUSH [EBX].TGraphicTool.fData.Pen.Width
15794 MOVZX ECX, [EBX].TGraphicTool.fData.Pen.Join
15795 SHL ECX, 12
15796 MOVZX EDX, [EBX].TGraphicTool.fData.Pen.EndCap
15797 SHL EDX, 8
15798 OR EDX, ECX
15799 OR DL, byte ptr [EBX].TGraphicTool.fData.Pen.Style
15800 OR EDX, PS_GEOMETRIC
15801 PUSH EDX
15802 CALL ExtCreatePen
15804 POP ECX
15805 POP ECX
15806 POP ECX
15808 MOV [EBX].TGraphicTool.fHandle, EAX
15809 POP EBX
15811 @@exit:
15812 XCHG EAX, ECX
15813 end;
15814 {$ELSE ASM_VERSION} //Pascal
15815 function MakeGeometricPenHandle( Self_: PGraphicTool ): THandle;
15816 const
15817 PenStyles: array[ TPenStyle ] of Word =
15818 (PS_SOLID, PS_DASH, PS_DOT, PS_DASHDOT, PS_DASHDOTDOT, PS_NULL,
15819 PS_INSIDEFRAME);
15820 PenEndCapStyles: array[ TPenEndCap ] of Word =
15821 (PS_ENDCAP_ROUND, PS_ENDCAP_SQUARE, PS_ENDCAP_FLAT);
15822 PenJoinStyles: array[ TPenJoin ] of Word =
15823 (PS_JOIN_ROUND, PS_JOIN_BEVEL, PS_JOIN_MITER );
15825 LogBrush: TLogBrush;
15826 begin
15827 if Self_.fHandle = 0 then
15828 with Self_{-}^{+}, LogBrush do
15829 begin
15830 lbColor := Color2RGB( fData.Color );
15831 lbHatch := 0;
15832 if fData.Pen.BrushBitmap <> 0 then
15833 begin
15834 lbStyle := BS_PATTERN;
15835 lbHatch := fData.Pen.BrushBitmap;
15837 else
15838 case fData.Pen.BrushStyle of
15839 bsSolid: lbStyle := BS_SOLID;
15840 bsClear: lbStyle := BS_NULL;
15841 else begin
15842 lbStyle := BS_HATCHED;
15843 case fData.Pen.BrushStyle of
15844 bsHorizontal: lbHatch := HS_HORIZONTAL;
15845 bsVertical: lbHatch := HS_VERTICAL;
15846 bsFDiagonal: lbHatch := HS_FDIAGONAL;
15847 bsBDiagonal: lbHatch := HS_BDIAGONAL;
15848 bsCross: lbHatch := HS_CROSS;
15849 bsDiagCross: lbHatch := HS_DIAGCROSS;
15850 end;
15851 end;
15852 end;
15853 end;
15854 Self_.fHandle := ExtCreatePen( PS_GEOMETRIC or Byte( Self_.fData.Pen.Style ) or
15855 PenEndCapStyles[ Self_.fData.Pen.EndCap ] or
15856 PenJoinStyles[ Self_.fData.Pen.Join ],
15857 Self_.fData.Pen.Width, LogBrush, 0, nil );
15858 {Assert( Self_.fHandle <> 0, 'Error ' + Int2Str( GetLastError ) +
15859 ': ' + SysErrorMessage( GetLastError ) );}
15860 {$IFDEF DEBUG_GDIOBJECTS}
15861 Inc( PenCount );
15862 {$ENDIF}
15863 Result := Self_.fHandle;
15864 end;
15865 {$ENDIF ASM_VERSION}
15866 //[END MakeGeometricPenHandle]
15868 //[procedure TGraphicTool.SetFontWeight]
15869 procedure TGraphicTool.SetFontWeight(const Value: Integer);
15870 begin
15871 if fData.Font.Weight = Value then Exit;
15872 fData.Font.Weight := Value;
15873 Changed;
15874 end;
15876 //[procedure TGraphicTool.SetLogFontStruct]
15877 procedure TGraphicTool.SetLogFontStruct(const Value: TLogFont);
15878 begin
15879 if CompareMem(@fData.Font, @Value, SizeOf(TLogFont)) then Exit;
15880 Move(Value, fData.Font, SizeOF(TLogFont));
15881 Changed;
15882 end;
15884 //[function TGraphicTool.GetLogFontStruct]
15885 function TGraphicTool.GetLogFontStruct: TLogFont;
15886 begin
15887 Move(fData.Font, Result, SizeOf(TLogFont));
15888 end;
15901 { TCanvas }
15903 type
15904 TStock = Packed Record
15905 StockPen: HPEN;
15906 StockBrush: HBRUSH;
15907 StockFont: HFONT;
15908 end;
15911 Stock: TStock;
15913 //[destructor TCanvas.Destroy]
15914 destructor TCanvas.Destroy;
15915 begin
15916 Handle := 0;
15917 fPen.Free;
15918 fBrush.Free;
15919 fFont.Free;
15920 //if Assigned( GlobalCanvas_OnDestroyCanvas ) then
15921 // GlobalCanvas_OnDestroyCanvas( Self );
15922 inherited;
15923 end;
15925 {$IFDEF ASM_VERSION}
15926 //[function TCanvas.Assign]
15927 function TCanvas.Assign(SrcCanvas: PCanvas): Boolean;
15929 PUSH EBX
15930 PUSH ESI
15931 XCHG EBX, EAX
15932 MOV ESI, EDX
15934 MOV EAX, [EBX].fFont
15935 MOV EDX, [ESI].fFont
15936 CALL TGraphicTool.Assign
15937 MOV [EBX].fFont, EAX
15939 MOV EAX, [EBX].fBrush
15940 MOV EDX, [ESI].fBrush
15941 CALL TGraphicTool.Assign
15942 MOV [EBX].fBrush, EAX
15944 MOV EAX, [EBX].fPen
15945 MOV EDX, [ESI].fPen
15946 CALL TGraphicTool.Assign
15947 MOV [EBX].fPen, EAX
15949 CALL AssignChangeEvents
15951 MOV ECX, [EBX].fFont
15952 OR ECX, [EBX].fBrush
15953 OR ECX, [EBX].fPen
15954 SETNZ AL
15956 MOV EDX, [ESI].fPenPos.x
15957 MOV ECX, [ESI].fPenPos.y
15958 CMP EDX, [EBX].fPenPos.x
15959 JNE @@chg_penpos
15960 CMP ECX, [EBX].fPenPos.y
15961 JE @@1
15962 @@chg_penpos:
15963 MOV AL, 1
15964 MOV [EBX].fPenPos.x, EDX
15965 MOV [EBX].fPenPos.y, ECX
15966 @@1:
15967 MOV EDX, [ESI].fCopyMode
15968 CMP EDX, [EBX].fCopyMode
15969 JE @@2
15970 MOV [EBX].fCopyMode, EDX
15971 MOV AL, 1
15972 @@2:
15973 POP ESI
15974 POP EBX
15975 end;
15976 {$ELSE ASM_VERSION} //Pascal
15977 function TCanvas.Assign(SrcCanvas: PCanvas): Boolean;
15978 begin
15979 fFont := fFont.Assign( SrcCanvas.fFont );
15980 fBrush := fBrush.Assign( SrcCanvas.fBrush );
15981 fPen := fPen.Assign( SrcCanvas.fPen );
15982 AssignChangeEvents;
15983 Result := (fFont <> nil) or (fBrush <> nil) or (fPen <> nil);
15984 if (SrcCanvas.PenPos.x <> PenPos.x) or (SrcCanvas.PenPos.y <> PenPos.y) then
15985 begin
15986 Result := True;
15987 PenPos := SrcCanvas.PenPos;
15988 end;
15989 if SrcCanvas.ModeCopy <> ModeCopy then
15990 begin
15991 Result := True;
15992 ModeCopy := SrcCanvas.ModeCopy;
15993 end;
15994 end;
15995 {$ENDIF ASM_VERSION}
15997 {$IFDEF ASM_VERSION}
15998 //[procedure TCanvas.CreateBrush]
15999 procedure TCanvas.CreateBrush;
16001 PUSH EBX
16002 MOV EBX, EAX
16004 MOV ECX, [EAX].fBrush
16005 JECXZ @@chk_owner
16007 MOV EAX, ECX
16008 CALL TGraphicTool.GetHandle
16009 PUSH EAX
16011 MOV EAX, EBX
16012 CALL AssignChangeEvents
16014 MOV EAX, EBX
16015 CALL TCanvas.GetHandle
16016 PUSH EAX
16018 CALL SelectObject
16020 MOV EDX, [EBX].TCanvas.fBrush
16021 CMP [EDX].TGraphicTool.fData.Brush.Style, bsSolid
16023 MOV EAX, [EDX].TGraphicTool.fData.Color
16024 @@0:
16025 MOV EBX, [EBX].TCanvas.fHandle
16026 MOV ECX, offset[Color2RGB]
16027 JNZ @@1
16029 PUSH OPAQUE
16030 PUSH EBX
16032 CALL ECX //Color2RGB
16033 PUSH EAX
16034 PUSH EBX
16035 JMP @@2
16036 @@1:
16037 PUSH TRANSPARENT
16038 PUSH EBX
16040 CALL ECX //Color2RGB
16041 NOT EAX
16042 PUSH EAX
16043 PUSH EBX
16044 @@2:
16045 CALL SetBkColor
16046 CALL SetBkMode
16047 @@exit:
16048 POP EBX
16051 @@chk_owner:
16052 MOV ECX, [EBX].fOwnerControl
16053 JECXZ @@exit
16055 MOV EAX, [ECX].TControl.fColor
16056 XOR ECX, ECX
16057 JMP @@0
16058 end;
16059 {$ELSE ASM_VERSION} //Pascal
16060 procedure TCanvas.CreateBrush;
16061 begin
16062 //UnrealizeObject( Brush.Handle );
16063 // if GdiObject parameter of UnrealizeObject is brush handle,
16064 // this call does nothing (from Win32.hlp)
16066 if assigned( fBrush ) then
16067 begin
16068 SelectObject( GetHandle, fBrush.Handle );
16069 //fBrush.fOnChange := ObjectChanged;
16070 AssignChangeEvents;
16071 if fBrush.fData.Brush.Style = bsSolid then
16072 begin
16073 SetBkColor( fHandle, Color2RGB( fBrush.fData.Color ) );
16074 SetBkMode( fHandle, OPAQUE );
16076 else
16077 begin
16078 { Win95 doesn't draw brush hatches if bkcolor = brush color }
16079 { Since bkmode is transparent, nothing should use bkcolor anyway }
16080 SetBkColor( fHandle, not Color2RGB( fBrush.fData.Color ) );
16081 SetBkMode( fHandle, TRANSPARENT );
16082 end;
16084 else
16085 if Assigned( fOwnerControl ) then
16086 begin
16087 SetBkColor( GetHandle, Color2RGB( PControl( fOwnerControl ).fColor ) );
16088 SetBkMode( fHandle, OPAQUE );
16089 end;
16090 end;
16091 {$ENDIF ASM_VERSION}
16093 {$IFDEF ASM_VERSION}
16094 //[procedure TCanvas.CreateFont]
16095 procedure TCanvas.CreateFont;
16097 PUSH EBX
16098 MOV EBX, EAX
16100 MOV ECX, [EAX].TCanvas.fFont
16101 JECXZ @@chk_owner
16103 MOV EAX, [ECX].TGraphicTool.fData.Color
16104 PUSH ECX
16105 CALL Color2RGB
16106 XCHG EAX, [ESP]
16108 CALL TGraphicTool.GetHandle
16109 PUSH EAX
16111 MOV EAX, EBX
16112 CALL AssignChangeEvents;
16114 MOV EAX, EBX
16115 CALL TCanvas.GetHandle
16116 PUSH EAX
16117 MOV EBX, EAX
16119 CALL SelectObject
16121 @@set_txcolor:
16122 PUSH EBX
16123 CALL SetTextColor
16125 @@exit:
16126 POP EBX
16129 @@chk_owner:
16130 MOV ECX, [EBX].fOwnerControl
16131 JECXZ @@exit
16133 MOV EBX, [EBX].fHandle
16134 MOV EAX, [ECX].TControl.fTextColor
16135 CALL Color2RGB
16136 PUSH EAX
16137 JMP @@set_txcolor
16138 end;
16139 {$ELSE ASM_VERSION} //Pascal
16140 procedure TCanvas.CreateFont;
16141 begin
16142 if assigned( fFont ) then
16143 begin
16144 SelectObject( GetHandle, fFont.Handle );
16145 SetTextColor( fHandle, Color2RGB( fFont.fData.Color ) );
16146 //fFont.fOnChange := ObjectChanged;
16147 AssignChangeEvents;
16149 else
16150 if Assigned( fOwnerControl ) then
16151 begin
16152 SetTextColor( fHandle, Color2RGB( PControl( fOwnerControl ).fTextColor ) );
16153 end;
16154 end;
16155 {$ENDIF ASM_VERSION}
16157 {$IFDEF ASM_VERSION}
16158 //[procedure TCanvas.CreatePen]
16159 procedure TCanvas.CreatePen;
16161 MOV ECX, [EAX].TCanvas.fPen
16162 JECXZ @@exit
16164 PUSH EBX
16165 MOV EBX, EAX
16167 MOV DL, [ECX].TGraphicTool.fData.Pen.Mode
16168 MOVZX EDX, DL
16169 INC EDX
16170 PUSH EDX
16172 MOV EAX, ECX
16173 CALL TGraphicTool.GetHandle
16174 PUSH EAX
16176 MOV EAX, EBX
16177 CALL AssignChangeEvents
16179 MOV EAX, EBX
16180 CALL TCanvas.GetHandle
16181 PUSH EAX
16182 MOV EBX, EAX
16184 CALL SelectObject
16185 PUSH EBX
16186 CALL SetROP2
16188 POP EBX
16189 @@exit:
16190 end;
16191 {$ELSE ASM_VERSION} //Pascal
16192 procedure TCanvas.CreatePen;
16193 begin
16194 if assigned( fPen ) then
16195 begin
16196 SelectObject( GetHandle, fPen.Handle );
16197 SetROP2( fHandle, Ord( fPen.fData.Pen.Mode ) + 1 );
16198 //fPen.fOnChange := ObjectChanged;
16199 AssignChangeEvents;
16200 end;
16201 end;
16202 {$ENDIF ASM_VERSION}
16204 //[function TCanvas.GetPixels]
16205 function TCanvas.GetPixels(X, Y: Integer): TColor;
16206 begin
16207 RequiredState( HandleValid );
16208 Result := Windows.GetPixel(FHandle, X, Y);
16209 end;
16211 //[procedure TCanvas.SetPixels]
16212 procedure TCanvas.SetPixels(X, Y: Integer; const Value: TColor);
16213 begin
16214 Changing;
16215 RequiredState( HandleValid );
16216 Windows.SetPixel(FHandle, X, Y, Color2RGB( Value ));
16217 end;
16219 {$IFDEF ASM_VERSION}
16220 //[procedure TCanvas.DeselectHandles]
16221 procedure TCanvas.DeselectHandles;
16223 PUSH EBX
16224 PUSH ESI
16225 PUSH EDI
16226 LEA EBX, [EAX].TCanvas.fState
16227 //CALL TCanvas.GetHandle
16228 MOV EAX, [EAX].TCanvas.fHandle
16229 TEST EAX, EAX
16230 JZ @@exit
16232 MOVZX EDX, byte ptr[EBX]
16233 AND DL, PenValid or BrushValid or FontValid
16234 JZ @@exit
16236 PUSH EAX
16237 LEA EDI, [Stock]
16239 MOV ECX, [EDI]
16240 INC ECX
16241 LOOP @@1
16243 MOV ESI, offset[ GetStockObject ]
16245 PUSH BLACK_PEN
16246 CALL ESI
16247 STOSD
16249 PUSH HOLLOW_BRUSH
16250 CALL ESI
16251 STOSD
16253 PUSH SYSTEM_FONT
16254 CALL ESI
16255 STOSD
16257 @@1:
16258 LEA ESI, [Stock]
16259 POP EDX
16261 LODSD
16262 PUSH EAX
16263 PUSH EDX
16265 LODSD
16266 PUSH EAX
16267 PUSH EDX
16269 LODSD
16270 PUSH EAX
16271 PUSH EDX
16273 MOV ESI, offset[ SelectObject ]
16274 CALL ESI
16275 CALL ESI
16276 CALL ESI
16278 AND byte ptr [EBX], not( PenValid or BrushValid or FontValid )
16279 @@exit:
16280 POP EDI
16281 POP ESI
16282 POP EBX
16283 end;
16284 {$ELSE ASM_VERSION} //Pascal
16285 procedure TCanvas.DeselectHandles;
16286 begin
16287 //if (GetHandle <> 0) and
16288 if (fHandle <> 0) and
16289 LongBool(fState and (PenValid or BrushValid or FontValid)) then
16290 with Stock do
16291 begin
16292 if StockPen = 0 then
16293 begin
16294 StockPen := GetStockObject(BLACK_PEN);
16295 StockBrush := GetStockObject(HOLLOW_BRUSH);
16296 StockFont := GetStockObject(SYSTEM_FONT);
16297 end;
16298 SelectObject( fHandle, StockPen );
16299 SelectObject( fHandle, StockBrush );
16300 SelectObject( fHandle, StockFont );
16301 fState := fState and not( PenValid or BrushValid or FontValid );
16302 end;
16303 end;
16304 {$ENDIF ASM_VERSION}
16306 {$IFDEF ASM_VERSION}
16307 //[function TCanvas.RequiredState]
16308 function TCanvas.RequiredState(ReqState: DWORD): Integer; stdcall;
16310 PUSH EBX
16311 PUSH ESI
16312 MOV EBX, ReqState
16313 MOV ESI, [EBP+8] //Self
16314 MOV EAX, ESI
16315 TEST BL, ChangingCanvas
16316 JZ @@1
16317 CALL Changing
16318 @@1: AND BL, 0Fh
16320 TEST BL, HandleValid
16321 JZ @@2
16322 CALL TCanvas.GetHandle
16323 TEST EAX, EAX
16324 JZ @@ret_0
16325 @@2:
16326 MOV AL, [ESI].TCanvas.fState
16327 NOT EAX
16328 AND BL, AL
16329 JZ @@ret_handle
16331 TEST BL, FontValid
16332 JZ @@3
16333 MOV EAX, ESI
16334 CALL CreateFont
16335 @@3: TEST BL, PenValid
16336 JZ @@5
16337 MOV EAX, ESI
16338 CALL CreatePen
16339 MOV ECX, [ESI].TCanvas.fPen
16340 JCXZ @@5
16341 MOV AL, [ECX].TGraphicTool.fData.Pen.Style
16342 DEC AL
16343 {$IFDEF PARANOIA}
16344 DB $2C, 3
16345 {$ELSE}
16346 SUB AL, 3
16347 {$ENDIF}
16348 JB @@6
16349 @@5: TEST BL, BrushValid
16350 JZ @@7
16351 @@6: MOV EAX, ESI
16352 CALL CreateBrush
16353 @@7: OR [ESI].TCanvas.fState, BL
16354 @@ret_handle:
16355 MOV EAX, [ESI].TCanvas.fHandle
16356 @@ret_0:
16357 POP ESI
16358 POP EBX
16359 end;
16360 {$ELSE ASM_VERSION} //Pascal
16361 function TCanvas.RequiredState(ReqState: DWORD): Integer; stdcall;
16363 NeededState: Byte;
16364 begin
16365 if Boolean(ReqState and ChangingCanvas) then
16366 Changing;
16367 ReqState := ReqState and 15;
16368 NeededState := Byte( ReqState ) and not fState;
16369 Result := 0;
16370 if Boolean(ReqState and HandleValid) then
16371 begin
16372 if GetHandle = 0 then Exit;
16373 // Important!
16374 end;
16375 if NeededState <> 0 then
16376 begin
16377 if Boolean( NeededState and FontValid ) then
16378 CreateFont;
16379 if Boolean( NeededState and PenValid ) then
16380 begin
16381 CreatePen;
16382 if assigned( fPen ) then
16383 if fPen.fData.Pen.Style in [psDash, psDot, psDashDot, psDashDotDot] then
16384 NeededState := NeededState or BrushValid;
16385 end;
16386 if Boolean( NeededState and BrushValid ) then
16387 CreateBrush;
16388 fState := fState or NeededState;
16389 end;
16390 Result := fHandle;
16391 end;
16392 {$ENDIF ASM_VERSION}
16394 {$IFDEF ASM_VERSION}
16395 //[procedure TCanvas.SetHandle]
16396 procedure TCanvas.SetHandle(Value: HDC);
16398 PUSH EBX
16399 MOV EBX, EAX
16400 MOV ECX, [EBX].fHandle
16401 CMP ECX, EDX
16402 JZ @@exit
16403 JECXZ @@chk_val
16405 PUSH EDX
16406 PUSH ECX
16407 CALL DeselectHandles
16408 POP EDX
16410 MOV ECX, [EBX].fOwnerControl
16411 JECXZ @@chk_Release
16412 CMP [ECX].TControl.fPaintDC, EDX
16413 JE @@clr_Handle
16415 @@chk_Release:
16416 PUSH EDX
16417 CMP [EBX].fOnGetHandle.TMethod.Code, offset[TControl.DC2Canvas]
16418 JNE @@deldc
16419 PUSH [ECX].TControl.fHandle
16420 CALL ReleaseDC
16421 JMP @@clr_Handle
16422 @@deldc:
16423 CALL DeleteDC
16425 @@clr_Handle:
16426 XOR ECX, ECX
16427 MOV [EBX].TCanvas.fHandle, ECX
16428 MOV [EBX].TCanvas.fIsPaintDC, CL
16429 AND [EBX].TCanvas.fState, not HandleValid
16431 POP EDX
16432 @@chk_val:
16433 TEST EDX, EDX
16434 JZ @@exit
16436 OR [EBX].TCanvas.fState, HandleValid
16437 MOV [EBX].TCanvas.fHandle, EDX
16438 LEA EDX, [EBX].TCanvas.fPenPos
16439 MOV EAX, EBX
16440 CALL SetPenPos
16442 @@exit: POP EBX
16443 end;
16444 {$ELSE ASM_VERSION} //Pascal
16445 procedure TCanvas.SetHandle(Value: HDC);
16446 {$IFDEF F_P}
16447 var Ptr1: Pointer;
16448 {$ENDIF F_P}
16449 begin
16450 if fHandle = Value then Exit;
16451 if fHandle <> 0 then
16452 begin
16453 DeselectHandles;
16454 {if not fIsPaintDC and
16455 not( assigned(fOwnerControl) and
16456 PControl(fOwnerControl).fDoubleBuffered )
16457 then}
16458 if not( assigned(fOwnerControl) and
16459 (PControl(fOwnerControl).fPaintDC = fHandle) ) then
16460 begin
16461 {$IFDEF F_P}
16462 Ptr1 := Self;
16464 MOV EAX, [Ptr1]
16465 MOV EAX, [EAX].TCanvas.fOnGetHandle
16466 MOV [Ptr1], EAX
16467 end [ 'EAX' ];
16468 if Ptr1 = @ TControl.DC2Canvas then
16469 {$ELSE DELPHI}
16470 //////////////////// SLAG
16471 if TMethod(fOnGetHandle).Code =
16472 @TControl.Dc2Canvas then
16473 {$ENDIF F_P/DELPHI}
16474 ReleaseDC(PControl(fOwnerControl).Handle, fHandle )
16475 else
16476 DeleteDC( fHandle );
16477 ////////////////////
16478 end;
16479 fHandle := 0;
16480 fIsPaintDC := False;
16481 fState := fState and not HandleValid;
16482 end;
16483 if Value <> 0 then
16484 begin
16485 fState := fState or HandleValid;
16486 fHandle := Value;
16487 SetPenPos( fPenPos );
16488 end;
16489 end;
16490 {$ENDIF ASM_VERSION}
16492 {$IFDEF ASM_VERSION}
16493 //[procedure TCanvas.SetPenPos]
16494 procedure TCanvas.SetPenPos(const Value: TPoint);
16496 MOV ECX, [EDX].TPoint.y
16497 MOV EDX, [EDX].TPoint.x
16498 MOV [EAX].fPenPos.x, EDX
16499 MOV [EAX].fPenPos.y, ECX
16500 CALL MoveTo
16501 end;
16502 {$ELSE ASM_VERSION} //Pascal
16503 procedure TCanvas.SetPenPos(const Value: TPoint);
16504 begin
16505 fPenPos := Value;
16506 MoveTo( Value.x, Value.y );
16507 end;
16508 {$ENDIF ASM_VERSION}
16510 {$IFDEF ASM_VERSION}
16511 //[procedure TCanvas.Changing]
16512 procedure TCanvas.Changing;
16514 PUSHAD
16515 MOV ECX, [EAX].fOnChange.TMethod.Code
16516 JECXZ @@exit
16517 XCHG EDX, EAX
16518 MOV EAX, [EDX].fOnChange.TMethod.Data
16519 CALL ECX
16520 @@exit:
16521 POPAD
16522 end;
16523 {$ELSE ASM_VERSION} //Pascal
16524 procedure TCanvas.Changing;
16525 begin
16526 if Assigned( fOnChange ) then
16527 fOnChange( @Self );
16528 end;
16529 {$ENDIF ASM_VERSION}
16531 {$IFDEF ASM_VERSION}
16532 //[procedure TCanvas.Arc]
16533 procedure TCanvas.Arc(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
16535 PUSH ESI
16537 PUSH HandleValid or PenValid or ChangingCanvas
16538 PUSH dword ptr [EBP+8]
16539 CALL RequiredState
16541 MOV EDX, EAX
16543 LEA ESI, [Y4]
16546 XOR ECX, ECX
16547 MOV CL, 8
16548 @@1:
16549 LODSD
16550 PUSH EAX
16552 LOOP @@1
16555 PUSH EDX //Canvas.fHandle
16556 CALL Windows.Arc
16557 POP ESI
16558 end;
16559 {$ELSE ASM_VERSION} //Pascal
16560 procedure TCanvas.Arc(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
16561 begin
16562 RequiredState( HandleValid or PenValid or ChangingCanvas );
16563 Windows.Arc(FHandle, X1, Y1, X2, Y2, X3, Y3, X4, Y4);
16564 end;
16565 {$ENDIF ASM_VERSION}
16567 {$IFDEF ASM_VERSION}
16568 //[procedure TCanvas.Chord]
16569 procedure TCanvas.Chord(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
16571 PUSH HandleValid or PenValid or BrushValid or ChangingCanvas
16572 PUSH dword ptr [EBP + 8]
16573 CALL RequiredState
16575 MOV EDX, EAX
16577 PUSH ESI
16578 LEA ESI, [Y4]
16581 XOR ECX, ECX
16582 MOV CL, 8
16583 @@1:
16584 LODSD
16585 PUSH EAX
16587 LOOP @@1
16590 PUSH EDX //Canvas.fHandle
16591 CALL Windows.Chord
16592 POP ESI
16593 end;
16594 {$ELSE ASM_VERSION} //Pascal
16595 procedure TCanvas.Chord(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
16596 begin
16597 RequiredState( HandleValid or PenValid or BrushValid or ChangingCanvas );
16598 Windows.Chord(FHandle, X1, Y1, X2, Y2, X3, Y3, X4, Y4);
16599 end;
16600 {$ENDIF ASM_VERSION}
16602 {$IFDEF ASM_VERSION}
16603 //[procedure TCanvas.CopyRect]
16604 procedure TCanvas.CopyRect(const DstRect: TRect; SrcCanvas: PCanvas;
16605 const SrcRect: TRect);
16607 PUSH ESI
16608 PUSH EDI
16610 PUSH [EAX].fCopyMode
16612 PUSH EDX
16614 PUSH HandleValid or BrushValid
16615 PUSH ECX
16617 PUSH HandleValid or FontValid or BrushValid or ChangingCanvas
16618 PUSH EAX
16619 MOV ESI, offset[ RequiredState ]
16620 CALL ESI
16621 MOV EDI, EAX // EDI = @Self.fHandle
16623 CALL ESI
16624 MOV EDX, EAX // EDX = SrcCanvas.fHandle
16626 POP ECX // ECX = @DstRect
16628 MOV ESI, [SrcRect]
16630 MOV EAX, [ESI].TRect.Bottom
16631 SUB EAX, [ESI].TRect.Top
16632 PUSH EAX
16634 MOV EAX, [ESI].TRect.Right
16635 SUB EAX, [ESI].TRect.Left
16636 PUSH EAX
16638 PUSH [ESI].TRect.Top
16640 LODSD
16641 PUSH EAX
16643 PUSH EDX
16645 MOV EAX, [ECX].TRect.Bottom
16646 MOV EDX, [ECX].TRect.Top
16647 SUB EAX, EDX
16648 PUSH EAX
16650 MOV EAX, [ECX].TRect.Right
16651 MOV ESI, [ECX].TRect.Left
16652 SUB EAX, ESI
16653 PUSH EAX
16655 PUSH EDX
16657 PUSH ESI
16659 PUSH EDI
16661 CALL StretchBlt
16663 POP EDI
16664 POP ESI
16665 end;
16666 {$ELSE ASM_VERSION} //Pascal
16667 procedure TCanvas.CopyRect(const DstRect: TRect; SrcCanvas: PCanvas;
16668 const SrcRect: TRect);
16669 begin
16670 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
16671 SrcCanvas.RequiredState( HandleValid or BrushValid );
16672 StretchBlt( fHandle, DstRect.Left, DstRect.Top, DstRect.Right - DstRect.Left,
16673 DstRect.Bottom - DstRect.Top, SrcCanvas.Handle, SrcRect.Left, SrcRect.Top,
16674 SrcRect.Right - SrcRect.Left, SrcRect.Bottom - SrcRect.Top, ModeCopy);
16675 end;
16676 {$ENDIF ASM_VERSION}
16678 {$IFDEF ASM_VERSION}
16679 //[procedure TCanvas.DrawFocusRect]
16680 procedure TCanvas.DrawFocusRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
16682 PUSH EDX
16684 PUSH HandleValid or BrushValid or FontValid or ChangingCanvas
16685 PUSH EAX
16686 CALL RequiredState
16688 PUSH EAX
16689 CALL Windows.DrawFocusRect
16690 end;
16691 {$ELSE ASM_VERSION} //Pascal
16692 procedure TCanvas.DrawFocusRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
16693 begin
16694 RequiredState( HandleValid or BrushValid or FontValid or ChangingCanvas );
16695 Windows.DrawFocusRect(FHandle, Rect);
16696 end;
16697 {$ENDIF ASM_VERSION}
16699 {$IFDEF ASM_VERSION}
16700 //[procedure TCanvas.Ellipse]
16701 procedure TCanvas.Ellipse(X1, Y1, X2, Y2: Integer);
16703 PUSH [Y2]
16704 PUSH [X2]
16705 PUSH ECX
16706 PUSH EDX
16708 PUSH HandleValid or PenValid or BrushValid or ChangingCanvas
16709 PUSH EAX
16710 CALL RequiredState
16712 PUSH EAX
16713 CALL Windows.Ellipse
16714 end;
16715 {$ELSE ASM_VERSION} //Pascal
16716 procedure TCanvas.Ellipse(X1, Y1, X2, Y2: Integer);
16717 begin
16718 RequiredState( HandleValid or PenValid or BrushValid or ChangingCanvas );
16719 Windows.Ellipse(FHandle, X1, Y1, X2, Y2);
16720 end;
16721 {$ENDIF ASM_VERSION}
16723 {$IFDEF ASM_VERSION}
16724 //[procedure TCanvas.FillRect]
16725 procedure TCanvas.FillRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
16727 PUSH EBX
16728 XCHG EBX, EAX
16729 PUSH EDX
16730 PUSH HandleValid or BrushValid or ChangingCanvas
16731 PUSH EBX
16732 CALL RequiredState
16733 MOV ECX, [EBX].fBrush
16734 JECXZ @@chk_ctl
16736 @@fill_with_Brush:
16737 XCHG EAX, ECX
16738 CALL TGraphicTool.GetHandle
16739 POP EDX
16740 PUSH EAX
16741 JMP @@fin
16742 @@chk_ctl:
16743 MOV ECX, [EBX].fOwnerControl
16744 JECXZ @@dflt_fill
16745 XCHG EAX, ECX
16746 MOV ECX, [EAX].TControl.fBrush
16747 INC ECX
16748 LOOP @@fill_with_Brush
16749 MOV EAX, [EAX].TControl.fColor
16750 CALL Color2RGB
16751 PUSH EAX
16752 CALL CreateSolidBrush
16753 POP EDX
16754 PUSH EAX
16755 PUSH EAX
16756 PUSH EDX
16757 PUSH [EBX].fHandle
16758 CALL Windows.FillRect
16759 CALL DeleteObject
16760 POP EBX
16762 @@dflt_fill:
16763 POP EDX
16764 PUSH COLOR_WINDOW + 1
16765 @@fin:
16766 PUSH EDX
16767 PUSH [EBX].fHandle
16768 CALL Windows.FillRect
16769 POP EBX
16770 end;
16771 {$ELSE ASM_VERSION} //Pascal
16772 procedure TCanvas.FillRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
16773 var Br: HBrush;
16774 begin
16775 RequiredState( HandleValid or BrushValid or ChangingCanvas );
16776 if assigned( fBrush ) then
16777 begin
16778 Windows.FillRect(fHandle, Rect, fBrush.Handle);
16780 else
16781 if assigned( fOwnerControl ) then
16782 begin
16783 if assigned( PControl( fOwnerControl ).fBrush ) then
16784 Windows.FillRect( fHandle, Rect, PControl( fOwnerControl ).fBrush.Handle )
16785 else
16786 begin
16787 Br := CreateSolidBrush( Color2RGB(PControl(fOwnerControl).fColor) );
16788 Windows.FillRect(fHandle, Rect, Br );
16789 DeleteObject( Br );
16790 end;
16792 else
16793 begin
16794 Windows.FillRect(fHandle, Rect, HBrush(COLOR_WINDOW + 1) );
16795 end;
16796 end;
16797 {$ENDIF ASM_VERSION}
16799 {$IFDEF ASM_VERSION}
16800 //[procedure TCanvas.FillRgn]
16801 procedure TCanvas.FillRgn(const Rgn: HRgn);
16803 PUSH EBX
16804 XCHG EBX, EAX
16805 PUSH EDX
16807 PUSH HandleValid or BrushValid or ChangingCanvas
16808 PUSH EBX
16809 CALL RequiredState
16811 MOV ECX, [EBX].TCanvas.fBrush
16812 JECXZ @@1
16814 //PUSH [ECX].TGraphicTool.fData.Color
16815 //JMP @@cr_br
16817 @@fill_rgn_using_Brush:
16818 XCHG EAX, ECX
16819 CALL TGraphicTool.GetHandle
16820 POP EDX
16821 PUSH EAX
16822 PUSH EDX
16823 PUSH [EBX].fHandle
16824 CALL Windows.FillRgn
16825 JMP @@fin
16827 @@1: MOV ECX, [EBX].TCanvas.fOwnerControl
16828 MOV EAX, -1 // clWhite
16829 JECXZ @@2
16831 XCHG EAX, ECX
16832 MOV ECX, [EAX].TControl.fBrush
16833 INC ECX
16834 LOOP @@fill_rgn_using_Brush
16836 MOV EAX, [EAX].TControl.fColor
16837 @@2:
16838 CALL Color2RGB
16839 PUSH EAX
16840 CALL CreateSolidBrush // EAX = Br
16842 POP EDX // Rgn
16844 PUSH EAX //-------------------//
16845 PUSH EAX // Br
16846 PUSH EDX // Rgn
16847 PUSH [EBX].FHandle // fHandle
16848 CALL Windows.FillRgn
16850 CALL DeleteObject
16852 @@fin:
16853 POP EBX
16854 end;
16855 {$ELSE ASM_VERSION} //Pascal
16856 procedure TCanvas.FillRgn(const Rgn: HRgn);
16857 var Br : HBrush;
16858 begin
16859 RequiredState( HandleValid or BrushValid or ChangingCanvas );
16860 if assigned( fBrush ) then
16861 Windows.FillRgn(FHandle, Rgn, fBrush.Handle )
16862 else
16863 if assigned( fOwnerControl ) then
16864 begin
16865 if Assigned( PControl( fOwnerControl ).fBrush ) then
16866 Windows.FillRgn( FHandle, Rgn, PControl( fOwnerControl ).fBrush.Handle )
16867 else
16868 begin
16869 Br := CreateSolidBrush( Color2RGB(PControl(fOwnerControl).fColor) );
16870 Windows.FillRgn( fHandle, Rgn, Br );
16871 DeleteObject( Br );
16872 end;
16874 else
16875 begin
16876 Br := CreateSolidBrush( DWORD(clWindow) );
16877 Windows.FillRgn( fHandle, Rgn, Br );
16878 DeleteObject( Br );
16879 end;
16880 end;
16881 {$ENDIF ASM_VERSION}
16883 {$IFDEF ASM_!VERSION}
16884 //[procedure TCanvas.FloodFill]
16885 procedure TCanvas.FloodFill(X, Y: Integer; Color: TColor;
16886 FillStyle: TFillStyle);
16888 PUSH EBX
16889 MOV EBX, EAX
16891 MOVZX EAX, [FillStyle]
16892 TEST EAX, EAX
16893 MOV EAX, FLOODFILLSURFACE // = 1
16894 JZ @@1
16895 //MOV EAX, FLOODFILLBORDER // = 0
16896 DEC EAX
16897 @@1:
16898 PUSH EAX
16899 PUSH [Color]
16900 PUSH ECX
16901 PUSH EDX
16903 PUSH HandleValid or BrushValid or ChangingCanvas
16904 PUSH EBX
16905 CALL RequiredState
16906 PUSH EAX
16907 CALL Windows.ExtFloodFill
16909 POP EBX
16910 end;
16911 {$ELSE ASM_VERSION} //Pascal
16912 procedure TCanvas.FloodFill(X, Y: Integer; Color: TColor;
16913 FillStyle: TFillStyle);
16914 const
16915 FillStyles: array[TFillStyle] of Word =
16916 (FLOODFILLSURFACE, FLOODFILLBORDER);
16917 begin
16918 RequiredState( HandleValid or BrushValid or ChangingCanvas );
16919 Windows.ExtFloodFill(FHandle, X, Y, Color, FillStyles[FillStyle]);
16920 end;
16921 {$ENDIF ASM_VERSION}
16923 {$IFDEF ASM_VERSION}
16924 //[procedure TCanvas.FrameRect]
16925 procedure TCanvas.FrameRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
16927 PUSH EBX
16928 XCHG EBX, EAX
16929 PUSH EDX
16931 MOV ECX, [EBX].TCanvas.fBrush
16932 JECXZ @@1
16934 PUSH [ECX].TGraphicTool.fData.Color
16935 JMP @@cr_br
16937 @@1: MOV ECX, [EBX].TCanvas.fOwnerControl
16938 JECXZ @@2
16940 PUSH [ECX].TControl.fColor
16941 JMP @@cr_br
16943 @@2: PUSH clWhite
16944 @@cr_br:POP EAX // @Rect
16945 CALL Color2RGB
16946 PUSH EAX
16947 CALL CreateSolidBrush
16948 POP EDX
16949 PUSH EAX
16950 PUSH EAX
16951 PUSH EDX
16953 PUSH HandleValid or ChangingCanvas
16954 PUSH EBX
16955 ///MOV EBX, EDX
16956 CALL RequiredState
16958 PUSH EAX
16959 CALL Windows.FrameRect
16961 ///PUSH EBX
16962 CALL DeleteObject
16964 POP EBX
16965 end;
16966 {$ELSE ASM_VERSION} //Pascal
16967 procedure TCanvas.FrameRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
16968 var SolidBr : HBrush;
16969 begin
16970 RequiredState( HandleValid or ChangingCanvas );
16971 if assigned( fBrush ) then
16972 SolidBr := CreateSolidBrush( Color2RGB( fBrush.fData.Color ) )
16973 else
16974 if assigned( fOwnerControl ) then
16975 SolidBr := CreateSolidBrush( PControl(fOwnerControl).fColor )
16976 else
16977 SolidBr := CreateSolidBrush( clWhite );
16978 Windows.FrameRect(FHandle, Rect, SolidBr);
16979 DeleteObject( SolidBr );
16980 end;
16981 {$ENDIF ASM_VERSION}
16983 {$IFDEF ASM_VERSION}
16984 //[procedure TCanvas.LineTo]
16985 procedure TCanvas.LineTo(X, Y: Integer);
16987 PUSH ECX
16988 PUSH EDX
16989 PUSH HandleValid or PenValid or BrushValid or ChangingCanvas
16990 PUSH EAX
16991 CALL RequiredState
16992 PUSH EAX //Canvas.fHandle
16993 CALL Windows.LineTo
16994 end;
16995 {$ELSE ASM_VERSION} //Pascal
16996 procedure TCanvas.LineTo(X, Y: Integer);
16997 begin
16998 RequiredState( HandleValid or PenValid or BrushValid or ChangingCanvas );
16999 Windows.LineTo( fHandle, X, Y );
17000 end;
17001 {$ENDIF ASM_VERSION}
17003 {$IFDEF ASM_VERSION}
17004 //[procedure TCanvas.MoveTo]
17005 procedure TCanvas.MoveTo(X, Y: Integer);
17007 PUSH 0
17008 PUSH ECX
17009 PUSH EDX
17010 PUSH HandleValid
17011 PUSH EAX
17012 CALL RequiredState
17013 PUSH EAX //Canvas.fHandle
17014 CALL Windows.MoveToEx
17015 end;
17016 {$ELSE ASM_VERSION} //Pascal
17017 procedure TCanvas.MoveTo(X, Y: Integer);
17018 begin
17019 RequiredState( HandleValid );
17020 Windows.MoveToEx( fHandle, X, Y, nil );
17021 end;
17022 {$ENDIF ASM_VERSION}
17024 //[procedure TCanvas.ObjectChanged]
17025 procedure TCanvas.ObjectChanged(Sender: PGraphicTool);
17026 begin
17027 DeselectHandles;
17028 //if Assigned( GlobalCanvas_OnObjectChanged ) then
17029 // GlobalCanvas_OnObjectChanged( Sender );
17030 end;
17032 {$IFDEF ASM_VERSION}
17033 //[procedure TCanvas.Pie]
17034 procedure TCanvas.Pie(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
17036 PUSH HandleValid or PenValid or BrushValid or ChangingCanvas
17037 PUSH dword ptr [EBP + 8]
17038 CALL RequiredState
17040 MOV EDX, EAX
17042 PUSH ESI
17043 LEA ESI, [Y4]
17046 XOR ECX, ECX
17047 MOV CL, 8
17048 @@1:
17049 LODSD
17050 PUSH EAX
17052 LOOP @@1
17055 PUSH EDX //Canvas.fHandle
17056 CALL Windows.Pie
17057 POP ESI
17058 end;
17059 {$ELSE ASM_VERSION} //Pascal
17060 procedure TCanvas.Pie(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
17061 begin
17062 RequiredState( HandleValid or PenValid or BrushValid or ChangingCanvas );
17063 Windows.Pie( fHandle, X1, Y1, X2, Y2, X3, Y3, X4, Y4);
17064 end;
17065 {$ENDIF ASM_VERSION}
17067 {++}(*
17068 {$IFDEF F_P}
17069 //[Windows API FUNCTIONS ADDITIONAL DECLARATIONS FOR Free Pascal]
17070 function Windows_Polygon; external gdi32 name 'Polygon';
17071 function Windows_Polyline; external gdi32 name 'Polyline';
17072 function FillRect; external user32 name 'FillRect';
17073 function OffsetRect; external user32 name 'OffsetRect';
17074 function CreateAcceleratorTable; external user32 name 'CreateAcceleratorTableA';
17075 function TrackPopupMenu; external user32 name 'TrackPopupMenu';
17076 function AdjustTokenPrivileges(TokenHandle: THandle; DisableAllPrivileges: BOOL;
17077 const NewState: TTokenPrivileges; BufferLength: DWORD;
17078 var PreviousState: TTokenPrivileges; var ReturnLength: DWORD): BOOL; external advapi32 name 'AdjustTokenPrivileges';
17079 function InflateRect; external user32 name 'InflateRect';
17080 {$IFDEF F_P105ORBELOW}
17081 function InvalidateRect; external user32 name 'InvalidateRect';
17082 function ValidateRect; external user32 name 'ValidateRect';
17083 {$ENDIF F_P105ORBELOW}
17084 //[END OF Windows API FUNCTIONS ADDITIONAL DECLARATIONS FOR Free Pascal]
17085 {$ENDIF}
17086 *){--}
17088 {$IFDEF ASM_VERSION}
17089 //[procedure TCanvas.Polygon]
17090 procedure TCanvas.Polygon(const Points: array of TPoint);
17092 INC ECX
17093 PUSH ECX
17094 PUSH EDX
17096 PUSH HandleValid or PenValid or BrushValid or ChangingCanvas
17097 PUSH EAX
17098 CALL RequiredState
17100 PUSH EAX
17101 CALL Windows.Polygon
17102 end;
17103 {$ELSE ASM_VERSION} //Pascal
17104 procedure TCanvas.Polygon(const Points: array of TPoint);
17105 type
17106 PPoints = ^TPoints;
17107 TPoints = array[0..0] of TPoint;
17108 begin
17109 RequiredState( HandleValid or PenValid or BrushValid or ChangingCanvas );
17110 {$IFDEF F_P} Windows_Polygon
17111 {$ELSE DELPHI} Windows.Polygon
17112 {$ENDIF}( fHandle, PPoints(@Points)^, High(Points) + 1);
17113 end;
17114 {$ENDIF ASM_VERSION}
17116 {$IFDEF ASM_VERSION}
17117 //[procedure TCanvas.Polyline]
17118 procedure TCanvas.Polyline(const Points: array of TPoint);
17120 INC ECX
17121 PUSH ECX
17122 PUSH EDX
17124 PUSH HandleValid or PenValid or BrushValid or ChangingCanvas
17125 PUSH EAX
17126 CALL RequiredState
17128 PUSH EAX
17129 CALL Windows.Polyline
17130 end;
17131 {$ELSE ASM_VERSION} //Pascal
17132 procedure TCanvas.Polyline(const Points: array of TPoint);
17133 type
17134 PPoints = ^TPoints;
17135 TPoints = array[0..0] of TPoint;
17136 begin
17137 RequiredState( HandleValid or PenValid or BrushValid or ChangingCanvas );
17138 {$IFDEF F_P}Windows_Polyline
17139 {$ELSE DELPHI}Windows.Polyline
17140 {$ENDIF}( fHandle, PPoints(@Points)^, High(Points) + 1);
17141 end;
17142 {$ENDIF ASM_VERSION}
17144 {$IFDEF ASM_VERSION}
17145 //[procedure TCanvas.Rectangle]
17146 procedure TCanvas.Rectangle(X1, Y1, X2, Y2: Integer);
17148 PUSH [Y2]
17149 PUSH [X2]
17150 PUSH ECX
17151 PUSH EDX
17153 PUSH HandleValid or BrushValid or PenValid or ChangingCanvas
17154 PUSH EAX
17155 CALL RequiredState
17157 PUSH EAX
17158 CALL Windows.Rectangle
17159 end;
17160 {$ELSE ASM_VERSION} //Pascal
17161 procedure TCanvas.Rectangle(X1, Y1, X2, Y2: Integer);
17162 begin
17163 RequiredState( HandleValid or BrushValid or PenValid or ChangingCanvas );
17164 Windows.Rectangle( fHandle, X1, Y1, X2, Y2);
17165 end;
17166 {$ENDIF ASM_VERSION}
17168 {$IFDEF ASM_VERSION}
17169 //[procedure TCanvas.RoundRect]
17170 procedure TCanvas.RoundRect(X1, Y1, X2, Y2, X3, Y3: Integer);
17172 PUSH [Y3]
17173 PUSH [X3]
17174 PUSH [Y2]
17175 PUSH [X2]
17176 PUSH ECX
17177 PUSH EDX
17179 PUSH HandleValid or BrushValid or PenValid or ChangingCanvas
17180 PUSH EAX
17181 CALL RequiredState
17183 PUSH EAX
17184 CALL Windows.RoundRect
17185 end;
17186 {$ELSE ASM_VERSION} //Pascal
17187 procedure TCanvas.RoundRect(X1, Y1, X2, Y2, X3, Y3: Integer);
17188 begin
17189 RequiredState( HandleValid or BrushValid or PenValid or ChangingCanvas );
17190 Windows.RoundRect( fHandle, X1, Y1, X2, Y2, X3, Y3);
17191 end;
17192 {$ENDIF ASM_VERSION}
17194 {$IFDEF ASM_VERSION}
17195 //[procedure TCanvas.TextArea]
17196 procedure TCanvas.TextArea(const Text: String; var Sz: TSize;
17197 var P0: TPoint);
17199 PUSH EBX
17200 MOV EBX, EAX
17202 PUSH ECX
17203 CALL TextExtent
17204 POP EDX
17206 MOV ECX, [P0]
17207 XOR EAX, EAX
17208 MOV [ECX].TPoint.x, EAX
17209 MOV [ECX].TPoint.y, EAX
17211 CMP [GlobalCanvas_OnTextArea], EAX
17212 JZ @@exit
17213 MOV EAX, EBX
17214 CALL [GlobalCanvas_OnTextArea]
17216 @@exit:
17217 POP EBX
17218 end;
17219 {$ELSE ASM_VERSION} //Pascal
17220 procedure TCanvas.TextArea(const Text: String; var Sz: TSize;
17221 var P0: TPoint);
17222 begin
17223 Sz := TextExtent( Text );
17224 P0.x := 0; P0.y := 0;
17225 if Assigned( GlobalCanvas_OnTextArea ) then
17226 GlobalCanvas_OnTextArea( @Self, Sz, P0 );
17227 end;
17228 {$ENDIF ASM_VERSION}
17230 {$IFDEF ASM_VERSION}
17231 //[function TCanvas.TextExtent]
17232 function TCanvas.TextExtent(const Text: string): TSize;
17234 PUSH EBX
17235 PUSH ESI
17236 MOV EBX, EAX
17238 PUSH ECX // prepare @Result
17240 MOV EAX, EDX
17241 CALL System.@LStrLen
17242 PUSH EAX // prepare Length(Text)
17244 CALL EDX2PChar
17245 PUSH EDX // prepare PChar(Text)
17247 PUSH HandleValid or FontValid
17248 PUSH EBX
17249 CALL RequiredState
17251 XCHG ESI, EAX
17252 TEST ESI, ESI // ESI = fHandle before
17253 JNZ @@1
17255 PUSH ESI
17256 CALL CreateCompatibleDC
17258 MOV EDX, EBX
17259 XCHG EAX, EDX // EAX := @Self; EDX := DC
17260 CALL SetHandle
17261 @@1:
17262 //********************************************************** // Added By M.Gerasimov
17264 CMP [EBX].TCanvas.fIsPaintDC, 1
17265 JZ @@2
17266 XOR ESI,ESI
17267 @@2:
17269 //********************************************************** // Added By M.Gerasimov
17270 PUSH HandleValid or FontValid
17271 PUSH EBX
17272 CALL RequiredState
17273 PUSH EAX // prepare DC
17275 CALL Windows.GetTextExtentPoint32
17277 TEST ESI, ESI
17278 JNZ @@exit
17280 XOR EDX, EDX
17281 XCHG EAX, EBX
17282 CALL SetHandle
17284 @@exit:
17285 POP ESI
17286 POP EBX
17287 end;
17288 {$ELSE ASM_VERSION} //Pascal
17289 function TCanvas.TextExtent(const Text: string): TSize;
17290 var DC : HDC;
17291 ClearHandle : Boolean;
17292 begin
17293 //Result.cX := 0;
17294 //Result.cY := 0;
17295 ClearHandle := False;
17296 RequiredState( HandleValid or FontValid );
17297 DC := fHandle;
17298 if DC = 0 then
17299 begin
17300 DC := CreateCompatibleDC( 0 );
17301 ClearHandle := True;
17302 SetHandle( DC );
17303 end;
17304 //********************************************************** // Added By Gerasimov
17306 If Not fIsPaintDC then ClearHandle := True;
17308 //********************************************************** // Added By Gerasimov
17309 RequiredState( HandleValid or FontValid );
17310 Windows.GetTextExtentPoint32( fHandle, PChar(Text), Length(Text), Result);
17311 if ClearHandle then
17312 SetHandle( 0 );
17313 { DC must be freed here automatically (never leaks):
17314 if Canvas created on base of existing DC, no memDC created,
17315 if Canvas has fHandle:HDC = 0, it is not fIsPaintDC always. }
17316 end;
17317 {$ENDIF ASM_VERSION}
17319 //[function TCanvas.TextHeight]
17320 function TCanvas.TextHeight(const Text: string): Integer;
17321 begin
17322 Result := TextExtent(Text).cY;
17323 end;
17325 {$IFDEF ASM_VERSION}
17326 //[procedure TCanvas.TextOut]
17327 procedure TCanvas.TextOut(X, Y: Integer; const Text: String); stdcall;
17329 PUSH EBX
17330 MOV EBX, [EBP+8]
17332 MOV EAX, [Text]
17333 PUSH EAX
17334 CALL System.@LStrLen
17335 XCHG EAX, [ESP] // prepare Length(Text)
17337 //CALL System.@LStrToPChar // string does not need to be null-terminated !
17338 PUSH EAX // prepare PChar(Text)
17339 PUSH [Y] // prepare Y
17340 PUSH [X] // prepare X
17342 PUSH HandleValid or FontValid or BrushValid or ChangingCanvas
17343 PUSH EBX
17344 CALL RequiredState
17345 PUSH EAX // prepare fHandle
17346 CALL Windows.TextOut
17348 { -- by suggetion of Alexey (Lecha2002)
17349 MOV EAX, EBX
17350 MOV EDX, [Text]
17351 CALL TextWidth
17352 MOV EDX, [X]
17353 ADD EDX, EAX
17355 MOV ECX, [Y]
17356 MOV EAX, EBX
17357 CALL MoveTo
17360 POP EBX
17361 end;
17362 {$ELSE ASM_VERSION} //Pascal
17363 procedure TCanvas.TextOut(X, Y: Integer; const Text: String); stdcall;
17364 begin
17365 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
17366 Windows.TextOut(FHandle, X, Y, PChar(Text), Length(Text));
17367 //MoveTo(X + TextWidth(Text), Y); -- by suggestion of Alexey (Lecha2002)
17368 end;
17369 {$ENDIF ASM_VERSION}
17371 {$IFDEF ASM_VERSION}
17372 //[procedure TCanvas.TextRect]
17373 procedure TCanvas.TextRect(const Rect: TRect; X, Y: Integer; const Text: string);
17375 PUSH EBX
17376 XCHG EBX, EAX
17378 PUSH 0 // prepare 0
17380 PUSH EDX
17381 PUSH ECX
17383 MOV EAX, [Text]
17384 //CALL System.@LStrToPChar
17385 PUSH EAX
17387 //MOV EAX, [Text]
17388 CALL System.@LStrLen
17390 POP ECX // ECX = @Text[1]
17392 POP EDX // EDX = X
17393 XCHG EAX, [ESP] // prepare Length(Text), EAX = @Rect
17394 PUSH ECX // prepare PChar(Text)
17395 PUSH EAX // prepare @Rect
17397 XOR EAX, EAX
17398 MOV AL, ETO_CLIPPED // = 4
17399 MOV ECX, [EBX].fBrush
17400 JECXZ @@opaque
17402 CMP [ECX].TGraphicTool.fData.Brush.Style, bsClear
17403 JZ @@txtout
17405 @@opaque:
17406 DB $0C, ETO_OPAQUE //OR AL, ETO_OPAQUE
17407 @@txtout:
17408 PUSH EAX // prepare Options
17409 PUSH [Y] // prepare Y
17410 PUSH EDX // prepare X
17412 PUSH HandleValid or FontValid or BrushValid or ChangingCanvas
17413 PUSH EBX
17414 CALL RequiredState // EAX = fHandle
17415 PUSH EAX // prepare fHandle
17417 CALL Windows.ExtTextOut
17419 POP EBX
17420 end;
17421 {$ELSE ASM_VERSION} //Pascal
17422 procedure TCanvas.TextRect(const Rect: TRect; X, Y: Integer; const Text: string);
17424 Options: Integer;
17425 begin
17426 //Changing;
17427 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
17428 Options := ETO_CLIPPED;
17429 if assigned( fBrush ) and (fBrush.fData.Brush.Style <> bsClear)
17430 or not assigned( fBrush ) then Inc(Options, ETO_OPAQUE);
17431 Windows.ExtTextOut( fHandle, X, Y, Options,
17432 @Rect, PChar(Text),
17433 Length(Text), nil);
17434 end;
17435 {$ENDIF ASM_VERSION}
17437 //[procedure TCanvas.ExtTextOut]
17438 procedure TCanvas.ExtTextOut( X, Y: Integer; Options: DWORD; const Rect: TRect; const Text: String;
17439 const Spacing: array of Integer );
17440 begin
17441 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
17442 Windows.ExtTextOut(FHandle, X, Y, Options, @Rect, PChar(Text), Length(Text), @Spacing[ 0 ]);
17443 end;
17445 //[procedure TCanvas.DrawText]
17446 procedure TCanvas.DrawText(Text:String; var Rect:TRect; Flags:DWord);
17447 begin
17448 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
17449 Windows.DrawText(Handle,PChar(Text),Length(Text),Rect,Flags);
17450 end;
17452 //[function TCanvas.ClipRect]
17453 function TCanvas.ClipRect: TRect;
17454 begin
17455 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
17456 GetClipBox(Handle, Result);
17457 end;
17459 //[function TCanvas.TextWidth]
17460 function TCanvas.TextWidth(const Text: string): Integer;
17461 begin
17462 Result := TextExtent(Text).cX;
17463 end;
17465 {$IFDEF ASM_VERSION}
17466 //[function TCanvas.GetBrush]
17467 function TCanvas.GetBrush: PGraphicTool;
17469 MOV ECX, [EAX].fBrush
17470 INC ECX
17471 LOOP @@exit
17473 PUSH EAX
17474 CALL NewBrush
17475 POP EDX
17476 PUSH EAX
17478 MOV [EDX].fBrush, EAX
17480 MOV [EAX].TGraphicTool.fOnChange.TMethod.Code, Offset[TCanvas.ObjectChanged]
17481 MOV [EAX].TGraphicTool.fOnChange.TMethod.Data, EDX
17482 MOV ECX, [EDX].fOwnerControl
17483 JECXZ @@1
17485 PUSH [ECX].TControl.fBrush
17486 MOV ECX, [ECX].TControl.fColor
17487 MOV [EAX].TGraphicTool.fData.Color, ECX
17488 POP EDX
17489 TEST EDX, EDX
17490 JZ @@1
17492 CALL TGraphicTool.Assign
17494 @@1: POP ECX
17496 @@exit: XCHG EAX, ECX
17497 end;
17498 {$ELSE ASM_VERSION} //Pascal
17499 function TCanvas.GetBrush: PGraphicTool;
17500 begin
17501 if not assigned( fBrush ) then
17502 begin
17503 fBrush := NewBrush;
17504 if assigned( fOwnerControl ) then
17505 begin
17506 fBrush.fData.Color := PControl(fOwnerControl).fColor;
17507 if assigned( PControl(fOwnerControl).fBrush ) then
17508 {fBrush := }fBrush.Assign( PControl(fOwnerControl).fBrush );
17509 // both statements above needed
17510 end;
17511 //fBrush.OnChange := ObjectChanged;
17512 AssignChangeEvents;
17513 end;
17514 Result := fBrush;
17515 end;
17516 {$ENDIF ASM_VERSION}
17518 {$IFDEF ASM_VERSION}
17519 //[function TCanvas.GetFont]
17520 function TCanvas.GetFont: PGraphicTool;
17522 MOV ECX, [EAX].TCanvas.fFont
17523 INC ECX
17524 LOOP @@exit
17526 PUSH EAX
17527 CALL NewFont
17528 POP EDX
17529 PUSH EAX
17531 MOV [EDX].TCanvas.fFont, EAX
17532 MOV [EAX].TGraphicTool.fOnChange.TMethod.Code, Offset[TCanvas.ObjectChanged]
17533 MOV [EAX].TGraphicTool.fOnChange.TMethod.Data, EDX
17535 MOV ECX, [EDX].fOwnerControl
17536 JECXZ @@1
17538 PUSH [ECX].TControl.fFont
17539 MOV ECX, [ECX].TControl.fTextColor
17540 MOV [EAX].TGraphicTool.fData.Color, ECX
17541 POP EDX
17542 TEST EDX, EDX
17543 JZ @@1
17545 CALL TGraphicTool.Assign
17547 @@1: POP ECX
17549 @@exit: MOV EAX, ECX
17550 end;
17551 {$ELSE ASM_VERSION} //Pascal
17552 function TCanvas.GetFont: PGraphicTool;
17553 begin
17554 if not assigned( fFont ) then
17555 begin
17556 fFont := NewFont;
17557 if assigned( fOwnerControl ) then
17558 begin
17559 fFont.Color := PControl(fOwnerControl).fTextColor;
17560 if assigned( PControl(fOwnerControl).fFont ) then
17561 {fFont := }fFont.Assign( PControl(fOwnerControl).fFont );
17562 end;
17563 //fFont.OnChange := ObjectChanged;
17564 AssignChangeEvents;
17565 end;
17566 Result := fFont;
17567 end;
17568 {$ENDIF ASM_VERSION}
17570 {$IFDEF ASM_VERSION}
17571 //[function TCanvas.GetPen]
17572 function TCanvas.GetPen: PGraphicTool;
17574 MOV ECX, [EAX].TCanvas.fPen
17575 INC ECX
17576 LOOP @@exit
17578 PUSH EAX
17579 CALL NewPen
17580 POP EDX
17581 MOV [EDX].fPen, EAX
17582 PUSH EAX
17583 MOV EAX, EDX
17584 CALL AssignChangeEvents
17585 POP ECX
17587 @@exit: MOV EAX, ECX
17588 end;
17589 {$ELSE ASM_VERSION} //Pascal
17590 function TCanvas.GetPen: PGraphicTool;
17591 begin
17592 if not assigned( fPen ) then
17593 begin
17594 fPen := NewPen;
17595 AssignChangeEvents;
17596 end;
17597 Result := fPen;
17598 end;
17599 {$ENDIF ASM_VERSION}
17601 {$IFDEF ASM_VERSION}
17602 //[function TCanvas.GetHandle]
17603 function TCanvas.GetHandle: HDC;
17605 CMP word ptr[EAX].fOnGetHandle.TMethod.Code+2, 0
17606 MOV EDX, EAX
17607 MOV EAX, [EDX].fHandle
17608 JZ @@exit
17609 MOV EAX, [EDX].fOnGetHandle.TMethod.Data
17610 PUSH EDX
17611 CALL [EDX].fOnGetHandle.TMethod.Code
17612 XCHG EAX, [ESP]
17613 POP EDX
17614 PUSH EDX
17615 CALL SetHandle
17616 POP EAX
17617 @@exit:
17618 end;
17619 {$ELSE ASM_VERSION} //Pascal
17620 function TCanvas.GetHandle: HDC;
17621 begin
17622 if assigned( fOnGetHandle ) then
17623 begin
17624 Result := fOnGetHandle( @Self );
17625 //fHandle := Result;
17626 SetHandle( Result );
17628 else
17629 Result := fHandle;
17630 end;
17631 {$ENDIF ASM_VERSION}
17633 {$IFDEF ASM_VERSION}
17634 //[procedure TCanvas.AssignChangeEvents]
17635 procedure TCanvas.AssignChangeEvents;
17637 PUSH ESI
17638 LEA ESI, [EAX].fBrush
17639 MOV CL, 3
17640 MOV EDX, EAX
17641 @@1: LODSD
17642 TEST EAX, EAX
17643 JZ @@nxt
17644 MOV [EAX].TGraphicTool.fOnChange.TMethod.Data, EDX
17645 MOV [EAX].TGraphicTool.fOnChange.TMethod.Code, offset[ ObjectChanged ]
17646 @@nxt: DEC CL
17647 JNZ @@1
17648 POP ESI
17649 end;
17650 {$ELSE ASM_VERSION} //Pascal
17651 procedure TCanvas.AssignChangeEvents;
17652 begin
17653 if assigned( fFont ) then
17654 fFont.fOnChange := ObjectChanged;
17655 if assigned( fBrush ) then
17656 fBrush.fOnChange := ObjectChanged;
17657 if assigned( fPen ) then
17658 fPen.fOnChange := ObjectChanged;
17659 end;
17660 {$ENDIF ASM_VERSION}
17662 {$IFNDEF _FPC}
17663 {$IFNDEF _D2}
17664 //[procedure TCanvas.WDrawText]
17665 procedure TCanvas.WDrawText(WText: WideString; var Rect: TRect;
17666 Flags: DWord);
17667 begin
17668 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
17669 Windows.DrawTextW(Handle,PWideChar(WText),Length(WText),Rect,Flags);
17670 end;
17672 //[procedure TCanvas.WExtTextOut]
17673 procedure TCanvas.WExtTextOut(X, Y: Integer; Options: DWORD;
17674 const Rect: TRect; const WText: WideString;
17675 const Spacing: array of Integer);
17676 begin
17677 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
17678 Windows.ExtTextOutW(FHandle, X, Y, Options, @Rect, PWideChar(WText), Length(WText), @Spacing[ 0 ]);
17679 end;
17681 //[procedure TCanvas.WTextOut]
17682 procedure TCanvas.WTextOut(X, Y: Integer; const WText: WideString);
17683 begin
17684 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
17685 Windows.TextOutW(FHandle, X, Y, PWideChar(WText), Length(WText));
17686 MoveTo(X + WTextWidth(WText), Y);
17687 end;
17689 //[procedure TCanvas.WTextRect]
17690 procedure TCanvas.WTextRect(const Rect: TRect; X, Y: Integer;
17691 const WText: WideString);
17693 Options: Integer;
17694 begin
17695 //Changing;
17696 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
17697 Options := ETO_CLIPPED;
17698 if assigned( fBrush ) and (fBrush.fData.Brush.Style <> bsClear)
17699 or not assigned( fBrush ) then Inc(Options, ETO_OPAQUE);
17700 Windows.ExtTextOutW( fHandle, X, Y, Options,
17701 @Rect, PWideChar(WText),
17702 Length(WText), nil);
17703 end;
17705 //[function TCanvas.WTextExtent]
17706 function TCanvas.WTextExtent(const WText: WideString): TSize;
17707 var DC : HDC;
17708 ClearHandle : Boolean;
17709 begin
17710 ClearHandle := False;
17711 RequiredState( HandleValid or FontValid );
17712 DC := fHandle;
17713 if DC = 0 then
17714 begin
17715 DC := CreateCompatibleDC( 0 );
17716 ClearHandle := True;
17717 SetHandle( DC );
17718 end;
17719 RequiredState( HandleValid or FontValid );
17720 Windows.GetTextExtentPoint32W( fHandle, PWideChar(WText), Length(WText), Result);
17721 if ClearHandle then
17722 SetHandle( 0 );
17723 end;
17725 //[function TCanvas.WTextHeight]
17726 function TCanvas.WTextHeight(const WText: WideString): Integer;
17727 begin
17728 Result := WTextExtent( WText ).cy;
17729 end;
17731 //[function TCanvas.WTextWidth]
17732 function TCanvas.WTextWidth(const WText: WideString): Integer;
17733 begin
17734 Result := WTextExtent( WText ).cx;
17735 end;
17736 {$ENDIF _D2}
17737 {$ENDIF _FPC}
17749 //[function MakeInt64]
17750 function MakeInt64( Lo, Hi: DWORD ): I64;
17751 begin
17752 Result.Lo := Lo;
17753 Result.Hi := Hi;
17754 end;
17756 //[function Int2Int64]
17757 function Int2Int64( X: Integer ): I64;
17759 MOV [EDX], EAX
17760 MOV ECX, EDX
17762 MOV [ECX+4], EDX
17763 end;
17765 //[procedure IncInt64]
17766 procedure IncInt64( var I64: I64; Delta: Integer );
17768 ADD [EAX], EDX
17769 ADC dword ptr [EAX+4], 0
17770 end;
17772 //[procedure DecInt64]
17773 procedure DecInt64( var I64: I64; Delta: Integer );
17775 SUB [EAX], EDX
17776 SBB dword ptr [EDX], 0
17777 end;
17779 //[function Add64]
17780 function Add64( const X, Y: I64 ): I64;
17782 PUSH ESI
17783 XCHG ESI, EAX
17784 LODSD
17785 ADD EAX, [EDX]
17786 MOV [ECX], EAX
17787 LODSD
17788 ADC EAX, [EDX+4]
17789 MOV [ECX+4], EAX
17790 POP ESI
17791 end;
17793 //[function Sub64]
17794 function Sub64( const X, Y: I64 ): I64;
17796 PUSH ESI
17797 XCHG ESI, EAX
17798 LODSD
17799 SUB EAX, [EDX]
17800 MOV [ECX], EAX
17801 LODSD
17802 SBB EAX, [EDX+4]
17803 MOV [ECX+4], EAX
17804 POP ESI
17805 end;
17807 //[function Neg64]
17808 function Neg64( const X: I64 ): I64;
17810 MOV ECX, [EAX]
17811 NEG ECX
17812 MOV [EDX], ECX
17813 MOV ECX, 0
17814 SBB ECX, [EAX+4]
17815 MOV [EDX+4], ECX
17816 end;
17818 //[function Mul64EDX]
17819 function Mul64EDX( const X: I64; M: Integer ): I64;
17821 PUSH ESI
17822 PUSH EDI
17823 XCHG ESI, EAX
17824 MOV EDI, ECX
17825 MOV ECX, EDX
17826 LODSD
17827 MUL ECX
17828 STOSD
17829 XCHG EDX, ECX
17830 LODSD
17831 MUL EDX
17832 ADD EAX, ECX
17833 STOSD
17834 POP EDI
17835 POP ESI
17836 end;
17838 //[FUNCTION Mul64i]
17839 {$IFDEF ASM_VERSION}
17840 function Mul64i( const X: I64; Mul: Integer ): I64;
17841 asm //cmd //opd
17842 TEST EDX, EDX
17843 PUSHFD
17844 JGE @@1
17845 NEG EDX
17846 @@1: PUSH ECX
17847 CALL Mul64EDX
17848 POP EAX
17849 POPFD
17850 JGE @@2
17851 MOV EDX, EAX
17852 CALL Neg64
17853 @@2:
17854 end;
17855 {$ELSE ASM_VERSION} //Pascal
17856 function Mul64i( const X: I64; Mul: Integer ): I64;
17857 var Minus: Boolean;
17858 begin
17859 Minus := FALSE;
17860 if Mul < 0 then
17861 begin
17862 Minus := TRUE;
17863 Mul := -Mul;
17864 end;
17865 Result := Mul64EDX( X, Mul );
17866 if Minus then
17867 Result := Neg64( Result );
17868 end;
17869 {$ENDIF ASM_VERSION}
17870 //[END Mul64i]
17872 //[function Div64EDX]
17873 function Div64EDX( const X: I64; D: Integer ): I64;
17875 PUSH ESI
17876 PUSH EDI
17877 XCHG ESI, EAX
17878 MOV EDI, ECX
17879 MOV ECX, EDX
17880 MOV EAX, [ESI+4]
17882 DIV ECX
17883 MOV [EDI+4], EAX
17884 LODSD
17885 DIV ECX
17886 STOSD
17887 POP EDI
17888 POP ESI
17889 end;
17891 //[FUNCTION Div64i]
17892 {$IFDEF ASM_VERSION}
17893 function Div64i( const X: I64; D: Integer ): I64;
17894 asm //cmd //opd
17895 PUSH EBX
17896 XOR EBX, EBX
17897 PUSH ESI
17898 XCHG ESI, EAX
17899 LODSD
17900 MOV [ECX], EAX
17901 LODSD
17902 MOV [ECX+4], EAX
17903 MOV ESI, ECX
17904 PUSH EDX
17905 XCHG EAX, ECX
17906 CALL Sgn64
17907 TEST EAX, EAX
17908 JGE @@1
17909 INC EBX
17910 MOV EAX, ESI
17911 MOV EDX, ESI
17912 CALL Neg64
17913 @@1: POP EDX
17914 TEST EDX, EDX
17915 JGE @@2
17916 XOR EBX, 1
17917 NEG EDX
17918 @@2: MOV EAX, ESI
17919 MOV ECX, ESI
17920 CALL Div64EDX
17921 DEC EBX
17922 JNZ @@3
17923 MOV EDX, ESI
17924 XCHG EAX, ESI
17925 CALL Neg64
17926 @@3: POP ESI
17927 POP EBX
17928 end;
17929 {$ELSE ASM_VERSION} //Pascal
17930 function Div64i( const X: I64; D: Integer ): I64;
17931 var Minus: Boolean;
17932 begin
17933 Minus := FALSE;
17934 if D < 0 then
17935 begin
17936 D := -D;
17937 Minus := TRUE;
17938 end;
17939 Result := X;
17940 if Sgn64( Result ) < 0 then
17941 begin
17942 Result := Neg64( Result );
17943 Minus := not Minus;
17944 end;
17945 Result := Div64EDX( Result, D );
17946 if Minus then
17947 Result := Neg64( Result );
17948 end;
17949 {$ENDIF ASM_VERSION}
17950 //[END Div64i]
17952 //[function Mod64i]
17953 function Mod64i( const X: I64; D: Integer ): Integer;
17954 begin
17955 Result := Sub64( X, Mul64i( Div64i( X, D ), D ) ).Lo;
17956 end;
17958 //[function Sgn64]
17959 function Sgn64( const X: I64 ): Integer;
17961 XOR EDX, EDX
17962 CMP [EAX+4], EDX
17963 XCHG EAX, EDX
17964 JG @@ret_1
17965 JL @@ret_neg
17966 CMP [EDX], EAX
17967 JZ @@exit
17968 @@ret_1:
17969 INC EAX
17971 @@ret_neg:
17972 DEC EAX
17973 @@exit:
17974 end;
17976 //[function Cmp64]
17977 function Cmp64( const X, Y: I64 ): Integer;
17978 begin
17979 Result := Sgn64( Sub64( X, Y ) );
17980 end;
17982 //[function Int64_2Str]
17983 function Int64_2Str( X: I64 ): String;
17984 var M: Boolean;
17985 Y: Integer;
17986 Buf: array[ 0..31 ] of Char;
17987 I: Integer;
17988 begin
17989 M := FALSE;
17990 case Sgn64( X ) of
17991 -1: begin M := TRUE; X := Neg64( X ); end;
17992 0: begin Result := '0'; Exit; end;
17993 end;
17994 I := 31;
17995 Buf[ 31 ] := #0;
17996 while Sgn64( X ) > 0 do
17997 begin
17998 Dec( I );
17999 Y := Mod64i( X, 10 );
18000 Buf[ I ] := Char( Y + Integer( '0' ) );
18001 X := Div64i( X, 10 );
18002 end;
18003 if M then
18004 begin
18005 Dec( I );
18006 Buf[ I ] := '-';
18007 end;
18008 Result := PChar( @Buf[ I ] );
18009 end;
18011 //[function Str2Int64]
18012 function Str2Int64( const S: String ): I64;
18013 var I: Integer;
18014 M: Boolean;
18015 begin
18016 Result.Lo := 0;
18017 Result.Hi := 0;
18018 I := 1;
18019 if S = '' then Exit;
18020 M := FALSE;
18021 if S[ 1 ] = '-' then
18022 begin
18023 M := TRUE;
18024 Inc( I );
18026 else
18027 if S[ 1 ] = '+' then
18028 Inc( I );
18029 while I <= Length( S ) do
18030 begin
18031 if not( S[ I ] in [ '0'..'9' ] ) then
18032 break;
18033 Result := Mul64i( Result, 10 );
18034 IncInt64( Result, Integer( S[ I ] ) - Integer( '0' ) );
18035 Inc( I );
18036 end;
18037 if M then
18038 Result := Neg64( Result );
18039 end;
18041 //[function Int64_2Double]
18042 function Int64_2Double( const X: I64 ): Double;
18044 FILD qword ptr [EAX]
18045 FSTP @Result
18046 end;
18048 //[function Double2Int64]
18049 function Double2Int64( D: Double ): I64;
18051 FLD D
18052 FISTP qword ptr [EAX]
18053 end;
18056 function IsNan(const AValue: Double): Boolean;
18057 {$IFDEF _D2orD3}
18058 type PI64 = ^I64;
18059 {$ENDIF}
18060 begin
18062 Result := (PI64(@AValue).Hi and $7FF00000 = $7FF00000) and
18063 ((PI64(@AValue).Hi and $000FFFFF <> 0) or (PI64(@AValue).Lo <> 0));
18064 {+}{++}(*Result := AValue = NAN;*){--}
18065 end;
18067 //[function IntPower]
18068 function IntPower(Base: Extended; Exponent: Integer): Extended;
18069 {$IFDEF F_P}
18070 begin
18071 if Exponent = 0 then
18072 begin
18073 Result := 1.0;
18074 Exit;
18075 end;
18076 if Exponent < 0 then
18077 begin
18078 Exponent := -Exponent;
18079 Base := 1.0 / Base;
18080 end;
18081 Result := Base;
18082 REPEAT
18083 Result := Result * Base;
18084 Dec( Exponent );
18085 UNTIL Exponent <= 0;
18086 end;
18087 {$ELSE DELPHI}
18088 // This version of code by Galkov:
18089 // Changes in comparison to Delphi standard:
18090 // no Overflow exception if Exponent is very big negative value
18091 // (just 0 in result in such case).
18093 fld1 { Result := 1 }
18094 test eax,eax // check Exponent for 0, return 0 ** 0 = 1
18095 jz @@3 // (though Mathematics says that this is not so...)
18096 fld Base
18097 jg @@2
18098 fdivr ST,ST(1) { Base := 1 / Base }
18099 neg eax
18100 jmp @@2
18101 @@1: fmul ST,ST { X := Base * Base }
18102 @@2: shr eax,1
18103 jnc @@1
18104 fmul ST(1),ST { Result := Result * X }
18105 jnz @@1
18106 fstp st { pop X from FPU stack }
18107 @@3: fwait
18108 end;
18109 (* version of code by Borland:
18111 mov ecx, eax
18113 fld1 { Result := 1 }
18114 xor eax, edx
18115 sub eax, edx { eax := Abs(Exponent) }
18116 jz @@3
18117 fld Base
18118 jmp @@2
18119 @@1: fmul ST, ST { X := Base * Base }
18120 @@2: shr eax,1
18121 jnc @@1
18122 fmul ST(1),ST { Result := Result * X }
18123 jnz @@1
18124 fstp st { pop X from FPU stack }
18125 cmp ecx, 0
18126 jge @@3
18127 fld1
18128 fdivrp { Result := 1 / Result }
18129 @@3:
18130 fwait
18131 end;*)
18132 {$ENDIF F_P/DELPHI}
18134 //[function Str2Double]
18135 function Str2Double( const S: String ): Double;
18136 var I: Integer;
18137 M, Pt: Boolean;
18138 D: Double;
18139 Ex: Integer;
18140 begin
18141 Result := 0.0;
18142 if S = '' then Exit;
18143 M := FALSE;
18144 I := 1;
18145 if S[ 1 ] = '-' then
18146 begin
18147 M := TRUE;
18148 Inc( I );
18149 end;
18150 Pt := FALSE;
18151 D := 1.0;
18152 while I <= Length( S ) do
18153 begin
18154 case S[ I ] of
18155 '.': if not Pt then Pt := TRUE else break;
18156 '0'..'9': if not Pt then
18157 Result := Result * 10.0 + Integer( S[ I ] ) - Integer( '0' )
18158 else
18159 begin
18160 D := D * 0.1;
18161 Result := Result + (Integer( S[ I ] ) - Integer( '0' )) * D;
18162 end;
18163 'e', 'E': begin
18164 Ex := Str2Int( CopyEnd( S, I + 1 ) );
18165 Result := Result * IntPower( 10.0, Ex );
18166 break;
18167 end;
18168 end;
18169 Inc( I );
18170 end;
18171 if M then
18172 Result := -Result;
18173 end;
18175 //[function TruncD]
18176 function TruncD( D: Double ): Double;
18179 FLD D
18180 PUSH ECX
18181 FNSTCW [ESP]
18182 POP ECX
18183 PUSH ECX
18184 OR byte ptr [ESP+1], $0C
18185 FLDCW [ESP]
18186 PUSH ECX
18187 FRNDINT
18188 FSTP @Result
18189 FLDCW [ESP]
18190 POP ECX
18191 POP ECX
18192 end;
18193 {+}{++}(*
18194 begin
18195 Result := Trunc( D );
18196 end;
18197 *){--}
18199 // Precision 15
18200 //[function Extended2Str]
18201 function Extended2Str( E: Extended ): String;
18202 function UnpackFromBuf( const Buf: array of Byte; N: Integer ): String;
18203 var I, J, K, L: Integer;
18204 begin
18205 SetLength( Result, 16 );
18206 J := 1;
18207 for I := 7 downto 0 do
18208 begin
18209 K := Buf[ I ] shr 4;
18210 Result[ J ] := Char( Ord('0') + K );
18211 Inc( J );
18212 K := Buf[ I ] and $F;
18213 Result[ J ] := Char( Ord('0') + K );
18214 Inc( J );
18215 end;
18217 Assert( Result[ 1 ] = '0', 'error!' );
18218 Delete( Result, 1, 1 );
18220 if N <= 0 then
18221 begin
18222 while N < 0 do
18223 begin
18224 Result := '0' + Result;
18225 Inc( N );
18226 end;
18227 Result := '0.' + Result;
18229 else
18230 if N < Length( Result ) then
18231 begin
18232 Result := Copy( Result, 1, N ) + '.' + CopyEnd( Result, N + 1 );
18234 else
18235 begin
18236 while N > Length( Result ) do
18237 begin
18238 Result := Result + '0';
18239 end;
18240 Exit;
18241 end;
18243 L := Length( Result );
18244 while L > 1 do
18245 begin
18246 if not (Result[ L ] in ['0','.']) then break;
18247 Dec( L );
18248 if Result[ L + 1 ] = '.' then break;
18249 end;
18250 if L < Length( Result ) then Delete( Result, L + 1, MaxInt );
18252 end;
18255 S: Boolean;
18256 var F: Extended;
18257 N: Integer;
18258 Buf1: array[ 0..9 ] of Byte;
18259 I10: Integer;
18260 begin
18261 Result := '0';
18262 if E = 0 then Exit;
18263 S := E < 0;
18264 if S then E := -E;
18266 N := 15;
18267 F := 5E12;
18268 I10 := 10;
18269 while E < F do
18270 begin
18271 Dec( N );
18272 E := E * I10;
18273 end;
18274 if N = 15 then
18275 while E >= 1E13 do
18276 begin
18277 Inc( N );
18278 E := E / I10;
18279 end;
18281 while TRUE do
18282 begin
18284 FLD [E]
18285 FBSTP [Buf1]
18286 end;
18287 if Buf1[ 7 ] <> 0 then break;
18288 E := E * I10;
18289 Dec( N );
18290 end;
18292 Result := UnpackFromBuf( Buf1, N );
18294 if S then Result := '-' + Result;
18295 end;
18297 //[function Double2Str]
18298 function Double2Str( D: Double ): String;
18299 begin
18300 Result := Extended2Str( D );
18301 end;
18303 //[function Double2StrEx]
18304 function Double2StrEx( D: Double ): String;
18305 var E, E1, E2: Double;
18306 S: String;
18307 begin
18308 Result := Double2Str( D );
18309 E := Str2Double( Result );
18310 E1 := E - D;
18311 if E1 < 0.0 then E1 := -E1;
18312 if E1 < 1e-307 then Exit;
18313 while TRUE do
18314 begin
18315 E := D - (E - D) * 0.3;
18316 S := Double2Str( E );
18317 if S = Result then break;
18318 E := Str2Double( S );
18319 E2 := E - D;
18320 if E2 < 0.0 then E2 := -E2;
18321 if E2 > E1 * 0.75 then break;
18322 Result := S;
18323 if E2 < E1 * 0.1 then break;
18324 end;
18325 end;
18327 //[function GetBits]
18328 function GetBits( N: DWORD; first, last: Byte ): DWord;
18329 {$IFDEF F_P}
18330 begin
18331 Result := 0;
18332 if last > 31 then last := 31;
18333 if first > last then Exit;
18334 Result := (N and not ($FFFFFFFF shl last)) shr first;
18335 end;
18336 {$ELSE DELPHI}
18338 XCHG EAX, EDX // (1) EDX=N, AL=first
18339 {$IFDEF PARANOIA}
18340 DB $3C, 31
18341 {$ELSE}
18342 CMP AL, 31 // first(AL) > 31 ?
18343 {$ENDIF}
18344 JBE @@1 // (2) åñëè äà, òî Result := 0;
18345 @@0:
18346 XOR EAX, EAX // (2)
18347 RET // (1)
18348 @@1:
18350 XCHG EAX, ECX // (1) AL = last CL = first
18351 SHR EDX, CL // (2) EDX = N shr first
18352 SUB AL, CL // (2) AL = last - first
18353 JL @@0 // (2) åñëè last < first òî Result := 0;
18355 {$IFDEF PARANOIA}
18356 DB $3C, 32
18357 {$ELSE}
18358 CMP AL, 32 // (2) last - first >= 32 ?
18359 {$ENDIF}
18360 XCHG ECX, EAX // (1) CL = last - first
18361 XCHG EAX, EDX // (1) EAX = N shr first
18362 JAE @@exit // (2) åñëè last - first > 31, òî Result := EAX;
18363 SBB EDX, EDX // (2) EDX = -1
18364 DEC EDX // (1) EDX = 1111...10 = -2
18365 SHL EDX, CL // (2) EDX = 111...100..0 (ãäå n(0)=last-first+1)
18366 NOT EDX // (2) EDX = ìàñêà 000..0111...1 (ãäå n(1)=last-first+1)
18367 AND EAX, EDX // (2)
18368 @@exit:
18369 // EAX = ðåçóëüòàò, (1 áàéò íà êîìàíäó RET)
18370 end;
18371 {$ENDIF F_P/DELPHI}
18373 //[function GetBitsL]
18374 function GetBitsL( N: DWORD; from, len: Byte ): DWord;
18375 {$IFDEF F_P}
18376 begin
18377 Result := GetBits( N, from, from + len - 1 );
18378 end;
18379 {$ELSE DELPHI}
18381 ADD CL, DL
18382 DEC CL
18383 JMP GetBits
18384 end;
18385 {$ENDIF F_P/DELPHI}
18387 //[FUNCTION Int2Hex]
18388 {$IFDEF ASM_VERSION}
18389 function Int2Hex( Value : DWord; Digits : Integer ) : String;
18392 // EAX = Value
18393 // EDX = Digits (actually DL needed)
18394 // ECX = @Result
18396 PUSH 0
18397 ADD ESP, -0Ch
18399 PUSH EBX
18400 PUSH ECX
18402 LEA EBX, [ESP+8+0Fh] // EBX := @Buf[ 15 ]
18403 AND EDX, $F
18405 @@loop: DEC EBX
18406 DEC EDX
18408 PUSH EAX
18409 {$IFDEF PARANOIA}
18410 DB $24, $0F
18411 {$ELSE}
18412 AND AL, 0Fh
18413 {$ENDIF}
18414 {$IFDEF PARANOIA}
18415 DB $3C, 9
18416 {$ELSE}
18417 CMP AL, 9
18418 {$ENDIF}
18419 JA @@10
18420 {$IFDEF PARANOIA}
18421 DB $04, 30h-41h+0Ah
18422 {$ELSE}
18423 ADD AL,30h-41h+0Ah
18424 {$ENDIF}
18425 @@10:
18426 {$IFDEF PARANOIA}
18427 DB $04, 41h-0Ah
18428 {$ELSE}
18429 ADD AL,41h-0Ah
18430 {$ENDIF}
18431 MOV byte ptr [EBX], AL
18432 POP EAX
18433 SHR EAX, 4
18435 JNZ @@loop
18437 TEST EDX, EDX
18438 JG @@loop
18440 POP EAX // EAX = @Result
18441 MOV EDX, EBX // EDX = @resulting string
18442 CALL System.@LStrFromPChar
18444 POP EBX
18445 ADD ESP, 10h
18447 {== by KSer - to test it only.
18448 function Int2Hex( Value : DWord; Digits : Integer ) : shortString;
18450 MOV [ECX], DL
18451 XADD EDX, ECX
18452 @@loop1:
18453 PUSH EAX
18454 db $24, $0F // and al,$0F
18456 //AAD
18457 DB $D5, $11
18458 db $04, $30 // add al,$30
18459 MOV [EDX], AL
18460 POP EAX
18461 SHR EAX, 4
18462 DEC EDX
18463 LOOP @@loop1
18465 end;
18466 {$ELSE ASM_VERSION} //Pascal (mixed)
18467 function Int2Hex( Value : DWord; Digits : Integer ) : String;
18468 var Buf: array[ 0..8 ] of Char;
18469 Dest : PChar;
18471 function HexDigit( B : Byte ) : Char;
18472 {$IFDEF F_P}
18473 const
18474 HexDigitChr: array[ 0..15 ] of Char = ( '0','1','2','3','4','5','6','7',
18475 '8','9','A','B','C','D','E','F' );
18476 begin
18477 Result := HexDigitChr[ B and $F ];
18478 end;
18479 {$ELSE DELPHI}
18481 {$IFDEF PARANOIA}
18482 DB $3C,9
18483 {$ELSE}
18484 CMP AL,9
18485 {$ENDIF}
18486 JA @@1
18487 {$IFDEF PARANOIA}
18488 DB $04, $30-$41+$0A
18489 {$ELSE}
18490 ADD AL,30h-41h+0Ah
18491 {$ENDIF}
18492 @@1:
18493 {$IFDEF PARANOIA}
18494 DB $04, $41-$0A
18495 {$ELSE}
18496 ADD AL,41h-0Ah
18497 {$ENDIF}
18498 end;
18499 {$ENDIF F_P/DELPHI}
18500 begin
18501 Dest := @Buf[ 8 ];
18502 Dest^ := #0;
18503 repeat
18504 Dec( Dest );
18505 Dest^ := '0';
18506 if Value <> 0 then
18507 begin
18508 Dest^ := HexDigit( Value and $F );
18509 Value := Value shr 4;
18510 end;
18511 Dec( Digits );
18512 until (Value = 0) and (Digits <= 0);
18513 Result := Dest;
18514 end;
18515 {$ENDIF ASM_VERSION}
18516 //[END Int2Hex]
18518 //[FUNCTION Hex2Int]
18519 {$IFDEF ASM_VERSION}
18520 function Hex2Int( const Value : String) : Integer;
18522 CALL EAX2PChar
18523 PUSH ESI
18524 XCHG ESI, EAX
18525 XOR EDX, EDX
18526 TEST ESI, ESI
18527 JE @@exit
18528 LODSB
18529 {$IFDEF PARANOIA}
18530 DB $3C, '$'
18531 {$ELSE}
18532 CMP AL, '$'
18533 {$ENDIF}
18534 JNE @@1
18535 @@0: LODSB
18536 @@1: TEST AL, AL
18537 JE @@exit
18538 {$IFDEF PARANOIA}
18539 DB $2C, '0'
18540 {$ELSE}
18541 SUB AL, '0'
18542 {$ENDIF}
18543 {$IFDEF PARANOIA}
18544 DB $3C, 9
18545 {$ELSE}
18546 CMP AL, '9' - '0'
18547 {$ENDIF}
18548 JBE @@3
18550 {$IFDEF PARANOIA}
18551 DB $2C, $11
18552 {$ELSE}
18553 SUB AL, 'A' - '0'
18554 {$ENDIF}
18555 {$IFDEF PARANOIA}
18556 DB $3C, 5
18557 {$ELSE}
18558 CMP AL, 'F' - 'A'
18559 {$ENDIF}
18560 JBE @@2
18562 {$IFDEF PARANOIA}
18563 DB $2C, 32
18564 {$ELSE}
18565 SUB AL, 32
18566 {$ENDIF}
18567 {$IFDEF PARANOIA}
18568 DB $3C, 5
18569 {$ELSE}
18570 CMP AL, 'F' - 'A'
18571 {$ENDIF}
18572 JA @@exit
18573 @@2:
18574 {$IFDEF PARANOIA}
18575 DB $04, 0Ah
18576 {$ELSE}
18577 ADD AL, 0Ah
18578 {$ENDIF}
18579 @@3:
18580 SHL EDX, 4
18581 ADD DL, AL
18582 JMP @@0
18584 @@exit: XCHG EAX, EDX
18585 POP ESI
18586 end;
18587 {$ELSE ASM_VERSION} //Pascal
18588 function Hex2Int( const Value : String) : Integer;
18589 var I : Integer;
18590 begin
18591 Result := 0;
18592 I := 1;
18593 if Value = '' then Exit;
18594 if Value[ 1 ] = '$' then Inc( I );
18595 while I <= Length( Value ) do
18596 begin
18597 if Value[ I ] in [ '0'..'9' ] then
18598 Result := (Result shl 4) or (Ord(Value[I]) - Ord('0'))
18599 else
18600 if Value[ I ] in [ 'A'..'F' ] then
18601 Result := (Result shl 4) or (Ord(Value[I]) - Ord('A') + 10)
18602 else
18603 if Value[ I ] in [ 'a'..'f' ] then
18604 Result := (Result shl 4) or (Ord(Value[I]) - Ord('a') + 10)
18605 else
18606 break;
18607 Inc( I );
18608 end;
18609 end;
18610 {$ENDIF ASM_VERSION}
18611 //[END Hex2Int]
18613 //[FUNCTION Octal2Int]
18614 function Octal2Int( const Value: String ) : Integer;
18615 var I: Integer;
18616 begin
18617 Result := 0;
18618 for I := 1 to Length( Value ) do
18619 begin
18620 if Value[ I ] in [ '0'..'7' ] then
18621 Result := Result * 8 + Ord( Value[ I ] ) - Ord( '0' )
18622 else break;
18623 end;
18624 end;
18625 //[END Octal2Int]
18627 //[FUNCTION Binary2Int]
18628 function Binary2Int( const Value: String ) : Integer;
18629 var I: Integer;
18630 begin
18631 Result := 0;
18632 for I := 1 to Length( Value ) do
18633 begin
18634 if Value[ I ] in [ '0'..'1' ] then
18635 Result := Result * 2 + Ord( Value[ I ] ) - Ord( '0' )
18636 else break;
18637 end;
18638 end;
18639 //[END Binary2Int]
18641 //[FUNCTION cHex2Int]
18642 {$IFDEF ASM_VERSION}
18643 function cHex2Int( const Value : String) : Integer;
18645 TEST EAX, EAX
18646 JZ @@exit
18647 CMP word ptr [EAX], '0x'
18648 JZ @@skip_2_chars
18649 CMP word ptr [EAX], '0X'
18650 JNZ @@2Hex2Int
18651 @@skip_2_chars:
18652 INC EAX
18653 INC EAX
18654 @@2Hex2Int:
18655 JMP Hex2Int
18656 @@exit:
18657 end;
18658 {$ELSE ASM_VERSION}
18659 function cHex2Int( const Value : String) : Integer;
18660 begin
18661 if StrEq( Copy( Value, 1, 2 ), '0x' ) then
18662 Result := Hex2Int( CopyEnd( Value, 3 ) )
18663 else Result := Hex2Int( Value );
18664 end;
18665 {$ENDIF ASM_VERSION}
18666 //[END cHex2Int]
18668 //[FUNCTION Int2Str]
18669 {$IFDEF ASM_VERSION}
18670 function Int2Str( Value : Integer ) : String;
18672 XOR ECX, ECX
18673 PUSH ECX
18674 ADD ESP, -0Ch
18676 PUSH EBX
18677 LEA EBX, [ESP + 15 + 4]
18678 PUSH EDX
18679 CMP EAX, ECX
18680 PUSHFD
18681 JGE @@1
18682 NEG EAX
18683 @@1:
18684 MOV CL, 10
18686 @@2:
18687 DEC EBX
18688 XOR EDX, EDX
18689 DIV ECX
18690 ADD DL, 30h
18691 MOV [EBX], DL
18692 TEST EAX, EAX
18693 JNZ @@2
18695 POPFD
18696 JGE @@3
18698 DEC EBX
18699 MOV byte ptr [EBX], '-'
18700 @@3:
18701 POP EAX
18702 MOV EDX, EBX
18703 CALL System.@LStrFromPChar
18705 POP EBX
18706 ADD ESP, 10h
18707 end;
18708 {$ELSE ASM_VERSION} //Pascal
18709 function Int2Str( Value : Integer ) : String;
18710 var Buf : array[ 0..15 ] of Char;
18711 Dst : PChar;
18712 Minus : Boolean;
18713 D: DWORD;
18714 begin
18715 Dst := @Buf[ 15 ];
18716 Dst^ := #0;
18717 Minus := False;
18718 if Value < 0 then
18719 begin
18720 Value := -Value;
18721 Minus := True;
18722 end;
18723 D := Value;
18724 repeat
18725 Dec( Dst );
18726 Dst^ := Char( (D mod 10) + Byte( '0' ) );
18727 D := D div 10;
18728 until D = 0;
18729 if Minus then
18730 begin
18731 Dec( Dst );
18732 Dst^ := '-';
18733 end;
18734 Result := Dst;
18735 end;
18736 {$ENDIF ASM_VERSION}
18737 //[END Int2Str]
18739 //[function UInt2Str]
18740 function UInt2Str( Value: DWORD ): String;
18741 var Buf : array[ 0..15 ] of Char;
18742 Dst : PChar;
18743 D: DWORD;
18744 begin
18745 Dst := @Buf[ 15 ];
18746 Dst^ := #0;
18747 D := Value;
18748 repeat
18749 Dec( Dst );
18750 Dst^ := Char( (D mod 10) + Byte( '0' ) );
18751 D := D div 10;
18752 until D = 0;
18753 Result := Dst;
18754 end;
18756 //[function Int2StrEx]
18757 function Int2StrEx( Value, MinWidth: Integer ): String;
18758 begin
18759 Result := Int2Str( Value );
18760 while Length( Result ) < MinWidth do
18761 Result := ' ' + Result;
18762 end;
18764 //[function Int2Rome]
18765 function Int2Rome( Value: Integer ): String;
18766 const RomeDigs: String = 'IVXLCDMT';
18767 function RomeNum( N, FromIdx: Integer ): String;
18768 begin
18769 CASE N OF
18770 1, 2, 3: Result := StrRepeat( RomeDigs[ FromIdx ], N );
18771 4: Result := RomeDigs[ FromIdx ] + RomeDigs[ FromIdx + 1 ];
18772 5, 6, 7, 8: Result := RomeDigs[ FromIdx + 1 ] + StrRepeat( RomeDigs[ FromIdx ],
18773 N - 5 );
18774 9: Result := RomeDigs[ FromIdx ] + RomeDigs[ FromIdx + 2 ]
18775 else Result := '';
18776 END;
18777 end;
18778 var I, J: Integer;
18779 begin
18780 Result := '';
18781 if Value < 1 then Exit;
18782 if Value > 8999 then Exit;
18783 // maximum possible is TMMMCMXCIX, i.e. 8999
18784 J := 1;
18785 for I := 1 to 3 do
18786 begin
18787 Result := RomeNum( Value mod 10, J ) + Result;
18788 Value := Value div 10;
18789 if Value = 0 then Exit;
18790 Inc( J, 2 );
18791 end;
18792 end;
18794 //[FUNCTION Int2Ths]
18795 {$IFDEF ASM_VERSION}
18796 function Int2Ths( I : Integer ) : String;
18798 PUSH EBP
18799 MOV EBP, ESP
18800 PUSH EAX
18801 PUSH EDX
18802 CALL Int2Str
18803 POP EDX
18804 POP EAX
18805 CMP EAX, 1000
18806 JL @@Exit
18807 PUSH EDX
18808 MOV EAX, [EDX]
18809 PUSH EAX
18810 CALL System.@LStrLen // EAX = Length(Result)
18811 POP EDX
18812 PUSH EDX // EDX = @Result[ 1 ]
18813 XOR ECX, ECX
18815 @@1:
18816 ROL ECX, 8
18817 DEC EAX
18818 MOV CL, [EDX+EAX]
18819 JZ @@fin
18820 CMP ECX, 300000h
18821 JL @@1
18823 PUSH ECX
18824 XOR ECX, ECX
18825 MOV CL, ','
18826 JMP @@1
18828 @@fin: CMP CX, ',-'
18829 JNE @@fin1
18830 MOV CH, 0 // this corrects -,ddd,...
18831 @@fin1: CMP ECX, 01000000h
18832 JGE @@fin2
18833 INC EAX
18834 ROL ECX, 8
18835 JMP @@fin1
18836 @@fin2: PUSH ECX
18838 LEA EDX, [ESP+EAX]
18839 MOV EAX, [EBP-4]
18840 CALL System.@LStrFromPChar
18841 @@Exit:
18842 MOV ESP, EBP
18843 POP EBP
18844 end;
18845 {$ELSE ASM_VERSION} //Pascal
18846 function Int2Ths( I : Integer ) : String;
18847 var S : String;
18848 begin
18849 S := Int2Str( I );
18850 Result := '';
18851 while S <> '' do
18852 begin
18853 if Result <> '' then
18854 Result := ',' + Result;
18855 Result := CopyTail( S, 3 ) + Result;
18856 S := Copy( S, 1, Length( S ) - 3 );
18857 end;
18858 if Copy( Result, 1, 2 ) = '-,' then
18859 Result := '-' + CopyEnd( Result, 3 );
18860 end;
18861 {$ENDIF ASM_VERSION}
18862 //[END Int2Ths]
18864 //[FUNCTION Int2Digs]
18865 {$IFDEF ASM_VERSION}
18866 function Int2Digs( Value, Digits : Integer ) : String;
18868 PUSH EBP
18869 MOV EBP, ESP
18870 PUSH EDX // [EBP-4] = Digits
18871 PUSH ECX
18872 MOV EDX, ECX
18873 CALL Int2Str
18874 POP ECX
18875 PUSH ECX // [EBP-8] = @Result
18876 MOV EAX, [ECX]
18877 PUSH EAX
18878 CALL System.@LStrLen
18879 POP EDX // EDX = @Result[1]
18880 MOV ECX, EAX // ECX = Length( Result )
18881 ADD EAX, EAX
18882 SUB ESP, EAX
18883 MOV EAX, ESP
18884 PUSHAD
18885 CALL StrCopy
18886 POPAD
18887 MOV EDX, EAX
18888 ADD ESP, -100
18889 CMP byte ptr [EDX], '-'
18890 PUSHFD
18891 JNE @@1
18892 INC EDX
18893 @@1:
18894 MOV EAX, [EBP-4] // EAX = Digits
18895 CMP ECX, EAX
18896 JGE @@2
18897 DEC EDX
18898 MOV byte ptr [EDX], '0'
18899 INC ECX
18900 JMP @@1
18901 @@2:
18902 POPFD
18903 JNE @@3
18904 DEC EDX
18905 MOV byte ptr [EDX], '-'
18906 @@3:
18907 MOV EAX, [EBP-8]
18908 CALL System.@LStrFromPChar
18909 MOV ESP, EBP
18910 POP EBP
18911 end;
18912 {$ELSE ASM_VERSION} //Pascal
18913 function Int2Digs( Value, Digits : Integer ) : String;
18914 var M : String;
18915 begin
18916 Result := Int2Str( Value );
18917 M := '';
18918 if Value < 0 then
18919 begin
18920 M := '-';
18921 Result := CopyEnd( Result, 2 );
18922 end;
18923 if Digits >= 0 then
18924 while Length( M + Result ) < Digits do
18925 Result := '0' + Result
18926 else
18927 while Length( Result ) < -Digits do
18928 Result := '0' + Result;
18929 Result := M + Result;
18930 end;
18931 {$ENDIF ASM_VERSION}
18932 //[END Int2Digs]
18934 //[FUNCTION Num2Bytes]
18935 {$IFDEF ASM_VERSION}
18936 function Num2Bytes( Value : Double ) : String;
18938 PUSH EBX
18939 PUSH ESI
18940 PUSH EDI
18941 MOV EBX, ESP
18942 MOV ESI, EAX
18944 MOV ECX, 4
18945 MOV EDX, 'TGMk'
18946 @@1:
18947 FLD [Value]
18948 @@10:
18949 FICOM dword ptr [@@1024]
18950 FSTSW AX
18951 SAHF
18952 JB @@2
18954 FIDIV dword ptr [@@1024]
18955 FST [Value]
18956 WAIT
18958 TEST DL, 20h
18959 JE @@ror
18960 AND DL, not 20h
18961 JMP @@nxt
18962 @@1024: DD 1024
18963 @@100: DD 100
18965 @@ror:
18966 ROR EDX, 8
18967 @@nxt:
18968 LOOP @@10
18969 @@2:
18970 TEST DL, 20h
18971 JZ @@3
18972 MOV DL, 0
18973 @@3: MOV DH, 0
18974 PUSH DX
18975 MOV EDI, ESP
18977 FLD ST(0)
18978 CALL System.@TRUNC
18979 {$IFDEF _D2orD3}
18980 PUSH 0
18981 {$ELSE}
18982 PUSH EDX
18983 {$ENDIF}
18984 PUSH EAX
18985 FILD qword ptr [ESP]
18986 POP EDX
18987 POP EDX
18989 MOV EDX, ESI
18990 CALL Int2Str
18992 FSUBP ST(1), ST
18993 FIMUL dword ptr [@@100]
18994 CALL System.@TRUNC
18996 TEST EAX, EAX
18997 JZ @@4
18999 XOR ECX, ECX
19000 MOV CL, 0Ah
19002 IDIV ECX
19003 TEST EDX, EDX
19004 JZ @@5
19006 MOV AH, DL
19007 SHL EAX, 16
19008 ADD EAX, '00. '
19009 PUSH EAX
19010 MOV EDI, ESP
19011 INC EDI
19012 JMP @@4
19014 @@5: SHL EAX, 8
19015 ADD AX, '0.'
19016 PUSH AX
19017 MOV EDI, ESP
19019 @@4:
19020 MOV EAX, [ESI]
19021 CALL System.@LStrLen
19022 ADD ESP, -100
19024 SUB EDI, EAX
19025 PUSH ESI
19026 PUSH EDI
19027 MOV ESI, [ESI]
19028 MOV ECX, EAX
19029 REP MOVSB
19031 POP EDX
19032 POP EAX
19033 CALL System.@LStrFromPChar
19035 MOV ESP, EBX
19036 POP EDI
19037 POP ESI
19038 POP EBX
19039 end;
19040 {$ELSE ASM_VERSION} //Pascal
19041 function Num2Bytes( Value : Double ) : String;
19042 const Suffix = 'KMGT';
19043 var V, I : Integer;
19044 begin
19045 Result := '';
19046 I := 0;
19047 while (Value >= 1024) and (I < 4) do
19048 begin
19049 Inc( I );
19050 Value := Value / 1024.0;
19051 end;
19052 Result := Int2Str( Trunc( Value ) );
19053 V := Trunc( (Value - Trunc( Value )) * 100 );
19054 if V <> 0 then
19055 begin
19056 if (V mod 10) = 0 then
19057 V := V div 10;
19058 Result := Result + ',' + Int2Str( V );
19059 end;
19060 if I > 0 then
19061 Result := Result + Suffix[ I ];
19062 end;
19063 {$ENDIF ASM_VERSION}
19064 //[END Num2Bytes]
19066 //[FUNCTION S2Int]
19067 {$IFDEF ASM_VERSION}
19068 function S2Int( S: PChar ): Integer;
19070 XCHG EDX, EAX
19071 XOR EAX, EAX
19072 TEST EDX, EDX
19073 JZ @@exit
19075 XOR ECX, ECX
19076 MOV CL, [EDX]
19077 INC EDX
19078 CMP CL, '-'
19079 PUSHFD
19080 JE @@0
19081 @@1: CMP CL, '+'
19082 JNE @@2
19083 @@0: MOV CL, [EDX]
19084 INC EDX
19085 @@2: SUB CL, '0'
19086 CMP CL, '9'-'0'
19087 JA @@fin
19088 LEA EAX, [EAX+EAX*4] //
19089 LEA EAX, [ECX+EAX*2] //
19090 JMP @@0
19091 @@fin: POPFD
19092 JNE @@exit
19093 NEG EAX
19094 @@exit:
19095 end;
19096 {$ELSE ASM_VERSION} //Pascal
19097 function S2Int( S: PChar ): Integer;
19098 var M : Integer;
19099 begin
19100 Result := 0;
19101 if S = '' then Exit;
19102 M := 1;
19103 if S^ = '-' then
19104 begin
19105 M := -1;
19106 Inc( S );
19108 else
19109 if S^ = '+' then
19110 Inc( S );
19111 while S^ in [ '0'..'9' ] do
19112 begin
19113 Result := Result * 10 + Integer( S^ ) - Integer( '0' );
19114 Inc( S );
19115 end;
19116 if M < 0 then
19117 Result := -Result;
19118 end;
19119 {$ENDIF ASM_VERSION}
19120 //[END S2Int]
19122 //[FUNCTION Str2Int]
19123 {$IFDEF ASM_VERSION}
19124 function Str2Int(const Value : String) : Integer;
19126 CALL EAX2PChar
19127 CALL S2Int
19128 end;
19129 {$ELSE ASM_VERSION} //Pascal
19130 function Str2Int(const Value : String) : Integer;
19131 begin
19132 Result := S2Int( PChar( Value ) );
19133 end;
19134 {$ENDIF ASM_VERSION}
19135 //[END Str2Int]
19137 //[function StrCopy]
19138 function StrCopy( Dest, Source: PChar ): PChar; assembler;
19140 {$IFDEF F_P}
19141 MOV EAX, [Dest]
19142 MOV EDX, [Source]
19143 {$ENDIF F_P}
19144 PUSH EDI
19145 PUSH ESI
19146 MOV ESI,EAX
19147 MOV EDI,EDX
19148 OR ECX, -1
19149 XOR AL,AL
19150 REPNE SCASB
19151 NOT ECX
19152 MOV EDI,ESI
19153 MOV ESI,EDX
19154 MOV EDX,ECX
19155 MOV EAX,EDI
19156 SHR ECX,2
19157 REP MOVSD
19158 MOV ECX,EDX
19159 AND ECX,3
19160 REP MOVSB
19161 POP ESI
19162 POP EDI
19163 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
19165 function StrCat( Dest, Source: PChar ): PChar;
19166 begin
19167 StrCopy( StrScan( Dest, #0 ), Source );
19168 Result := Dest;
19169 end;
19171 //[function StrScan]
19172 function StrScan(Str: PChar; Chr: Char): PChar; assembler;
19174 {$IFDEF F_P}
19175 MOV EAX, [Str]
19176 MOVZX EDX, [Chr]
19177 {$ENDIF}
19178 PUSH EDI
19179 PUSH EAX
19180 MOV EDI,Str
19181 OR ECX, -1
19182 XOR AL,AL
19183 REPNE SCASB
19184 NOT ECX
19185 POP EDI
19186 XCHG EAX, EDX
19187 REPNE SCASB
19189 XCHG EAX, EDI
19190 POP EDI
19192 JE @@1
19193 XOR EAX, EAX
19196 @@1: DEC EAX
19197 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
19199 //[function StrRScan]
19200 function StrRScan(const Str: PChar; Chr: Char): PChar; assembler;
19202 {$IFDEF F_P}
19203 MOV EAX, [Str]
19204 MOVZX EDX, [Chr]
19205 {$ENDIF F_P}
19206 PUSH EDI
19207 MOV EDI,Str
19208 MOV ECX,0FFFFFFFFH
19209 XOR AL,AL
19210 REPNE SCASB
19211 NOT ECX
19213 DEC EDI
19214 MOV AL,Chr
19215 REPNE SCASB
19216 MOV EAX,0
19217 JNE @@1
19218 MOV EAX,EDI
19219 INC EAX
19220 @@1: CLD
19221 POP EDI
19222 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
19224 //[function StrScanLen]
19225 function StrScanLen(Str: PChar; Chr: Char; Len: Integer): PChar; assembler;
19227 {$IFDEF F_P}
19228 MOV EAX, [Str]
19229 MOVZX EDX, [Chr]
19230 MOV ECX, [Len]
19231 {$ENDIF F_P}
19232 PUSH EDI
19233 XCHG EDI, EAX
19234 XCHG EAX, EDX
19235 REPNE SCASB
19237 XCHG EAX, EDI
19238 POP EDI
19239 { -> EAX => to next character after found or to the end of Str,
19240 ZF = 0 if character found. }
19241 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
19243 //[FUNCTION TrimLeft]
19244 {$IFDEF ASM_VERSION}
19245 function TrimLeft(const S: string): string;
19247 XCHG EAX, EDX
19248 CALL EDX2PChar
19249 DEC EDX
19250 @@1: INC EDX
19251 MOVZX ECX, byte ptr [EDX]
19252 JECXZ @@fin
19253 CMP CL, ' '
19254 JBE @@1
19255 @@fin:
19256 CALL System.@LStrFromPChar
19257 end;
19258 {$ELSE ASM_VERSION} //Pascal
19259 function TrimLeft(const S: string): string;
19261 I, L: Integer;
19262 begin
19263 L := Length(S);
19264 I := 1;
19265 while (I <= L) and (S[I] <= ' ') do Inc(I);
19266 Result := Copy(S, I, Maxint);
19267 end;
19268 {$ENDIF ASM_VERSION}
19269 //[END TrimLeft]
19271 //[FUNCTION TrimRight]
19272 {$IFDEF ASM_VERSION}
19273 function TrimRight(const S: string): string;
19275 PUSH EDX
19276 PUSH EAX
19278 PUSH EAX
19279 CALL System.@LStrLen
19280 XCHG EAX, [ESP]
19281 //CALL System.@LStrToPChar
19282 CALL EAX2PChar
19283 POP ECX
19284 INC ECX
19285 @@1: DEC ECX
19286 MOV DL, [EAX+ECX]
19287 JL @@fin
19288 CMP DL, ' '
19289 JBE @@1
19290 @@fin:
19291 INC ECX
19292 POP EAX
19293 XOR EDX, EDX
19294 INC EDX
19295 CALL System.@LStrCopy
19296 end;
19297 {$ELSE ASM_VERSION} //Pascal
19298 function TrimRight(const S: string): string;
19300 I: Integer;
19301 begin
19302 I := Length(S);
19303 while (I > 0) and (S[I] <= ' ') do Dec(I);
19304 Result := Copy(S, 1, I);
19305 end;
19306 {$ENDIF ASM_VERSION}
19307 //[END TrimRight]
19309 //[FUNCTION Trim]
19310 {$IFDEF ASM_VERSION}
19311 function Trim( const S : string): string;
19313 PUSH EDX
19314 CALL TrimRight
19315 POP EDX
19316 MOV EAX, [EDX]
19317 CALL TrimLeft
19318 end;
19319 {$ELSE ASM_VERSION} //Pascal
19320 function Trim( const S : string): string;
19321 begin
19322 Result := TrimLeft( TrimRight( S ) );
19323 end;
19324 {$ENDIF ASM_VERSION}
19325 //[END Trim]
19327 //[function RemoveSpaces]
19328 function RemoveSpaces( const S: String ): String;
19329 var I: Integer;
19330 begin
19331 Result := S;
19332 for I := Length( S ) downto 1 do
19333 if S[ I ] <= ' ' then Delete( Result, I, 1 );
19334 end;
19336 //[procedure Str2LowerCase]
19337 procedure Str2LowerCase( S: PChar );
19339 {$IFDEF F_P}
19340 MOV EAX, [S]
19341 {$ENDIF}
19342 XOR ECX, ECX
19343 @@1:
19344 MOV CL, byte ptr [EAX]
19345 JECXZ @@exit
19346 SUB CL, 'A'
19347 CMP CL, 'Z'-'A'
19348 JA @@2
19349 ADD byte ptr [EAX], 32
19350 @@2: INC EAX
19351 JMP @@1
19352 @@exit:
19353 end {$IFDEF F_P} [ 'EAX', 'ECX' ] {$ENDIF};
19355 //[FUNCTION LowerCase]
19356 {$IFDEF ASM_VERSION}
19357 function LowerCase(const S: string): string;
19359 PUSH ESI
19360 XCHG EAX, EDX
19361 PUSH EAX
19362 CALL System.@LStrAsg
19363 POP EAX
19365 CALL UniqueString
19367 PUSH EAX
19368 CALL System.@LStrLen
19369 POP ESI
19371 XCHG ECX, EAX
19373 JECXZ @@exit
19375 @@go:
19376 LODSB
19377 {$IFDEF PARANOIA}
19378 DB $2C, 'A'
19379 {$ELSE}
19380 SUB AL, 'A'
19381 {$ENDIF}
19382 {$IFDEF PARANOIA}
19383 DB $3C, 26
19384 {$ELSE}
19385 CMP AL, 'Z'-'A'+1
19386 {$ENDIF}
19387 JNB @@1
19389 ADD byte ptr [ESI - 1], 20h
19390 @@1:
19391 LOOP @@go
19392 @@exit:
19393 POP ESI
19394 end;
19395 {$ELSE ASM_VERSION} //Pascal
19396 function LowerCase(const S: string): string;
19397 var I : Integer;
19398 begin
19399 Result := S;
19400 for I := 1 to Length( S ) do
19401 if Result[ I ] in [ 'A'..'Z' ] then
19402 Inc( Result[ I ], 32 );
19403 end;
19404 {$ENDIF ASM_VERSION}
19405 //[END LowerCase]
19407 //[FUNCTION UpperCase]
19408 {$IFDEF ASM_VERSION}
19409 function UpperCase(const S: string): string;
19411 PUSH ESI
19412 XCHG EAX, EDX
19413 PUSH EAX
19414 CALL System.@LStrAsg
19415 POP EAX
19417 CALL UniqueString
19419 PUSH EAX
19420 CALL System.@LStrLen
19421 POP ESI
19423 XCHG ECX, EAX
19425 JECXZ @@exit
19427 @@go:
19428 LODSB
19429 {$IFDEF PARANOIA}
19430 DB $2C, 'a'
19431 {$ELSE}
19432 SUB AL, 'a'
19433 {$ENDIF}
19434 {$IFDEF PARANOIA}
19435 DB $3C, $1A
19436 {$ELSE}
19437 CMP AL, 'z'-'a'+1
19438 {$ENDIF}
19439 JNB @@1
19441 SUB byte ptr [ESI - 1], 20h
19442 @@1:
19443 LOOP @@go
19444 @@exit:
19445 POP ESI
19446 end;
19447 {$ELSE ASM_VERSION} //Pascal
19448 function UpperCase(const S: string): string;
19449 var I : Integer;
19450 begin
19451 Result := S;
19452 for I := 1 to Length( S ) do
19453 if Result[ I ] in [ 'a'..'z' ] then
19454 Dec( Result[ I ], 32 );
19455 end;
19456 {$ENDIF ASM_VERSION}
19457 //[END UpperCase]
19459 {$IFDEF F_P}
19460 //[function DummyStrFun]
19461 function DummyStrFun( const S: String ): String;
19462 begin
19463 Result := S;
19464 end;
19465 {$ENDIF F_P}
19467 //[FUNCTION CopyEnd]
19468 {$IFDEF ASM_VERSION}
19469 function CopyEnd( const S : String; Idx : Integer ) : String;
19471 PUSH ECX
19472 PUSH EAX
19473 PUSH EDX
19475 CALL System.@LStrLen
19477 POP EDX
19478 TEST EDX, EDX
19479 JG @@1
19480 XOR EDX, EDX
19481 INC EDX
19482 @@1:
19483 SUB EAX, EDX
19484 MOV ECX, EAX
19486 POP EAX
19487 JGE @@ret_end
19489 POP EAX
19490 JL System.@LStrClr
19492 @@ret_end:
19493 INC ECX
19494 CALL System.@LStrCopy
19495 end;
19496 {$ELSE ASM_VERSION} //Pascal
19497 function CopyEnd( const S : String; Idx : Integer ) : String;
19498 begin
19499 Result := Copy( S, Idx, MaxInt );
19500 end;
19501 {$ENDIF ASM_VERSION}
19502 //[END CopyEnd]
19504 //[FUNCTION CopyTail]
19505 {$IFDEF ASM_VERSION}
19506 function CopyTail( const S : String; Len : Integer ) : String;
19508 PUSH ECX
19509 PUSH EAX
19510 PUSH EDX
19511 CALL System.@LStrLen
19512 POP ECX
19513 CMP ECX, EAX
19514 {$IFDEF USE_CMOV}
19515 CMOVG ECX, EAX
19516 {$ELSE}
19517 JLE @@1
19518 MOV ECX, EAX
19519 @@1: {$ENDIF}
19521 MOV EDX, EAX
19522 SUB EDX, ECX
19523 INC EDX
19524 POP EAX
19525 CALL System.@LStrCopy
19526 end;
19527 {$ELSE ASM_VERSION} //Pascal
19528 function CopyTail( const S : String; Len : Integer ) : String;
19529 var L : Integer;
19530 begin
19531 L := Length( S );
19532 if L < Len then
19533 Len := L;
19534 Result := '';
19535 if Len = 0 then Exit;
19536 Result := Copy( S, L - Len + 1, Len );
19537 end;
19538 {$ENDIF ASM_VERSION}
19539 //[END CopyTail]
19541 //[PROCEDURE DeleteTail]
19542 {$IFDEF ASM_VERSION}
19543 procedure DeleteTail( var S : String; Len : Integer );
19545 PUSH EAX
19546 PUSH EDX
19547 MOV EAX, [EAX]
19548 CALL System.@LStrLen
19549 POP ECX
19550 CMP ECX, EAX
19551 {$IFDEF USE_CMOV}
19552 CMOVG ECX, EAX
19553 {$ELSE}
19554 JLE @@1
19555 MOV ECX, EAX
19556 @@1: {$ENDIF}
19558 MOV EDX, EAX
19559 SUB EDX, ECX
19560 INC EDX
19561 POP EAX
19562 CALL System.@LStrDelete
19563 end;
19564 {$ELSE ASM_VERSION} //Pascal
19565 procedure DeleteTail( var S : String; Len : Integer );
19566 var L : Integer;
19567 begin
19568 L := Length( S );
19569 if Len > L then
19570 Len := L;
19571 Delete( S, L - Len + 1, Len );
19572 end;
19573 {$ENDIF ASM_VERSION}
19574 //[END DeleteTail]
19576 //[FUNCTION IndexOfChar]
19577 {$IFDEF ASM_VERSION}
19578 function IndexOfChar( const S : String; Chr : Char ) : Integer;
19580 //PUSH EDX
19581 //CALL System.@LStrToPChar
19582 //POP EDX
19583 CALL EAX2PChar
19584 PUSH EAX
19585 CALL StrScan
19586 POP EDX
19587 TEST EAX, EAX
19588 JE @@exit__1
19589 SUB EAX, EDX
19590 INC EAX
19592 @@exit__1:
19593 DEC EAX
19594 end;
19595 {$ELSE ASM_VERSION} //Pascal
19596 function IndexOfChar( const S : String; Chr : Char ) : Integer;
19597 var P, F : PChar;
19598 begin
19599 P := PChar( S );
19600 F := StrScan( P, Chr );
19601 Result := -1;
19602 if F = nil then Exit;
19603 Result := Integer( F ) - Integer( P ) + 1;
19604 end;
19605 {$ENDIF ASM_VERSION}
19606 //[END IndexOfChar]
19608 //[FUNCTION IndexOfCharsMin]
19609 {$IFDEF ASM_VERSION}
19610 function IndexOfCharsMin( const S, Chars : String ) : Integer;
19612 PUSH ESI
19613 PUSH EAX
19614 CALL EDX2PChar
19615 MOV ESI, EDX
19617 XOR ECX, ECX
19618 DEC ECX
19620 @@1: LODSB
19621 TEST AL, AL
19622 JZ @@exit
19624 XCHG EDX, EAX
19625 POP EAX
19626 PUSH EAX
19628 PUSH ECX
19629 CALL IndexOfChar
19630 POP ECX
19631 TEST EAX, EAX
19632 JLE @@1
19634 TEST ECX, ECX
19635 JLE @@2
19636 CMP EAX, ECX
19637 JGE @@1
19638 @@2: //XCHG ECX, EAX
19639 //JMP @@1
19641 @@exit: XCHG EAX, ECX
19642 JL @@1
19643 POP ECX
19644 POP ESI
19645 end;
19646 {$ELSE ASM_VERSION} //Pascal
19647 function IndexOfCharsMin( const S, Chars : String ) : Integer;
19648 var I, J : Integer;
19649 begin
19650 Result := -1;
19651 for I := 1 to Length( Chars ) do
19652 begin
19653 J := IndexOfChar( S, Chars[ I ] );
19654 if J > 0 then
19655 begin
19656 if (Result < 0) or (J < Result) then
19657 Result := J;
19658 end;
19659 end;
19660 end;
19661 {$ENDIF ASM_VERSION}
19662 //[END IndexOfCharsMin]
19664 {$IFNDEF _FPC}
19665 {$IFNDEF _D2}
19666 //[function IndexOfWideCharsMin]
19667 function IndexOfWideCharsMin( const S, Chars : WideString ) : Integer;
19668 var I, J : Integer;
19669 begin
19670 Result := -1;
19671 for I := 1 to Length( Chars ) do
19672 begin
19673 J := pos( Chars[ I ], S );
19674 if J > 0 then
19675 begin
19676 if (Result < 0) or (J < Result) then
19677 Result := J;
19678 end;
19679 end;
19680 end;
19681 {$ENDIF _D2}
19682 {$ENDIF _FPC}
19684 //[FUNCTION IndexOfStr]
19685 {$IFDEF ASM_VERSION}
19686 function IndexOfStr( const S, Sub : String ) : Integer;
19688 PUSH EBX
19689 PUSH ESI
19690 PUSH EDI
19692 PUSH EAX
19693 MOV EAX, EDX
19694 PUSH EDX
19695 CALL System.@LStrLen
19696 MOV EDI, EAX
19697 POP EAX
19698 //CALL System.@LStrToPChar
19699 CALL EAX2PChar
19700 MOV BL, [EAX]
19701 XCHG EAX, [ESP]
19702 //CALL System.@LStrToPChar
19703 CALL EAX2PChar
19705 MOV ESI, EAX
19707 DEC EAX
19708 @@1: INC EAX
19709 MOV DL, BL
19710 CALL StrScan
19711 TEST EAX, EAX
19712 JE @@exit__1
19714 POP EDX
19715 PUSH EDX
19717 MOV ECX, EDI
19718 PUSH EAX
19719 CALL StrLComp
19720 POP EAX
19721 JNE @@1
19723 SUB EAX, ESI
19724 INC EAX
19725 JMP @@exit
19727 @@exit__1:
19728 DEC EAX
19729 @@exit:
19730 POP EDX
19731 POP EDI
19732 POP ESI
19733 POP EBX
19734 end;
19735 {$ELSE ASM_VERSION} //Pascal
19736 function IndexOfStr( const S, Sub : String ) : Integer;
19737 var I : Integer;
19738 begin
19739 Result := Length( S );
19740 if Sub = '' then Exit;
19741 Result := 0;
19742 if S = '' then Exit;
19743 if Length( Sub ) > Length( S ) then Exit;
19744 Result := 1;
19745 while Result + Length( Sub ) - 1 <= Length( S ) do
19746 begin
19747 I := IndexOfChar( CopyEnd( S, Result ), Sub[ 1 ] );
19748 if I <= 0 then break;
19749 Result := Result + I - 1;
19750 if Result <= 0 then Exit;
19751 if Copy( S, Result, Length( Sub ) ) = Sub then Exit;
19752 Inc( Result );
19753 end;
19754 Result := -1;
19755 end;
19756 {$ENDIF ASM_VERSION}
19757 //[END IndexOfStr]
19759 //[FUNCTION Parse]
19760 {$IFDEF ASM_VERSION} //???
19761 function Parse( var S : String; const Separators : String ) : String;
19763 PUSH EBX
19764 PUSH EDI
19765 MOV EBX, EAX
19767 PUSH ECX
19768 MOV EAX, [EBX]
19769 CALL IndexOfCharsMin
19770 INC EAX
19771 JNE @@1
19772 MOV EAX, [EBX]
19773 CALL System.@LStrLen
19774 INC EAX
19775 INC EAX
19776 @@1:
19777 DEC EAX
19778 MOV EDI, EAX
19779 MOV ECX, EAX
19780 DEC ECX
19781 XOR EDX, EDX
19782 INC EDX
19783 MOV EAX, [EBX]
19784 CALL System.@LStrCopy
19786 MOV EAX, [EBX]
19787 MOV EDX, EDI
19788 INC EDX
19789 MOV ECX, EBX
19790 CALL CopyEnd
19792 POP EDI
19793 POP EBX
19794 end;
19795 {$ELSE ASM_VERSION} //Pascal
19796 function Parse( var S : String; const Separators : String ) : String;
19797 var Pos : Integer;
19798 begin
19799 Pos := IndexOfCharsMin( S, Separators );
19800 if Pos <= 0 then
19801 Pos := Length( S ) + 1;
19802 Result := S;
19803 S := Copy( Result, Pos + 1, MaxInt );
19804 Result := Copy( Result, 1, Pos - 1 );
19805 end;
19806 {$ENDIF ASM_VERSION}
19807 //[END Parse]
19809 {$IFNDEF _FPC}
19810 {$IFNDEF _D2}
19811 //[function WParse]
19812 function WParse( var S : WideString; const Separators : WideString ) : WideString;
19813 var Pos : Integer;
19814 begin
19815 Pos := IndexOfWideCharsMin( S, Separators );
19816 if Pos <= 0 then
19817 Pos := Length( S ) + 1;
19818 Result := S;
19819 S := Copy( Result, Pos + 1, MaxInt );
19820 Result := Copy( Result, 1, Pos - 1 );
19821 end;
19822 {$ENDIF _D2}
19823 {$ENDIF _FPC}
19825 //[function ParsePascalString]
19826 function ParsePascalString( var S : String; const Separators : String ) : String;
19827 var Pos, Idx : Integer;
19828 Hex, Spc : boolean;
19829 procedure SkipSpaces;
19830 begin
19831 if not Spc then
19832 while (Length( S ) >= Pos) and (S[ Pos ] = ' ') do
19833 Inc( Pos );
19834 end;
19835 var Buf : String;
19836 Ou, Val : Integer;
19837 begin
19838 Pos := 1;
19839 Spc := IndexOfChar( Separators, ' ' ) >= 0;
19840 SkipSpaces;
19841 if Length( S ) < Pos then
19842 begin
19843 Result := S;
19844 S := '';
19845 exit;
19846 end;
19847 Buf := PChar( S );
19848 Ou := 1;
19849 if S[ Pos ] in [ '''', '#' ] then
19850 begin
19851 // skip here string constant expression
19852 while Pos <= Length( S ) do
19853 begin
19854 if S[ Pos ] = '''' then
19855 begin
19856 Inc( Pos );
19857 while Pos <= Length( S ) do
19858 begin
19859 if S[ Pos ] = '''' then
19860 if (Pos = Length( S )) or (S[ Pos+1 ] <> '''') then
19861 begin
19862 Inc( Pos );
19863 break;
19865 else Inc( Pos );
19866 Buf[ Ou ] := S[ Pos ];
19867 Inc( Ou );
19868 Inc( Pos );
19869 end;
19870 //if Pos < Length( S ) then Inc( Pos );
19872 else
19873 if S[ Pos ] = '#' then
19874 begin
19875 Inc( Pos ); Hex := False; Val := 0;
19876 if (Pos < Length( S )) and (S[ Pos ] = '$') then
19877 begin
19878 Inc( Pos ); Hex := True;
19879 end;
19880 Dec( Pos );
19881 while Pos < Length( S ) do
19882 begin
19883 Inc( Pos );
19884 if (S[ Pos ] in [ '0'..'9' ]) or
19885 Hex and (S[ Pos ] in [ 'a'..'f', 'A'..'F' ]) then
19886 begin
19887 if Hex then
19888 Val := Val * 16
19889 else
19890 Val := Val * 10;
19891 if S[ Pos ] <= '9' then
19892 Val := Val + Integer( S[ Pos ] ) - Integer( '0' )
19893 else
19894 if S[ Pos ] <= 'F' then
19895 Val := Val + 10 + Integer( S[ Pos ] ) - Integer( 'A' )
19896 else
19897 Val := Val + 10 + Integer( S[ Pos ] ) - Integer( 'a' );
19898 continue;
19899 end;
19900 Inc( Pos ); break;
19901 end;
19902 Buf[ Ou ] := Char( Val );
19903 Inc( Ou );
19905 else break;
19906 SkipSpaces;
19907 if S[ Pos ] <> '+' then break;
19908 SkipSpaces;
19909 end;
19910 end;
19911 Idx := IndexOfCharsMin( CopyEnd( S, Pos ), Separators );
19912 if Idx <= 0 then
19913 begin
19914 Result := Copy( Buf, 1, Ou - 1 ) + CopyEnd( S, Pos );
19915 S := '';
19917 else
19918 begin
19919 Result := Copy( Buf, 1, Ou - 1 ) + Copy( S, Pos, Idx - 1 );
19920 S := CopyEnd( S, Pos + Idx );
19921 end;
19922 end;
19924 //[function String2PascalStrExpr]
19925 function String2PascalStrExpr( const S : String ) : String;
19926 var I, Strt : Integer;
19927 function String2DoubleQuotas( const S : String ) : String;
19928 var I, J : Integer;
19929 begin
19930 if IndexOfChar( S, '''' ) <= 0 then
19931 Result := S
19932 else
19933 begin
19934 J := 0;
19935 for I := 1 to Length( S ) do
19936 if S[ I ] = '''' then Inc( J );
19937 SetLength( Result, Length( S ) + J );
19938 J := 1;
19939 for I := 1 to Length( S ) do
19940 begin
19941 Result[ J ] := S[ I ];
19942 Inc( J );
19943 if S[ I ] = '''' then
19944 begin
19945 Result[ J ] := '''';
19946 Inc( J );
19947 end;
19948 end;
19949 end;
19950 end;
19951 begin
19952 Result := '';
19953 if S = '' then
19954 begin
19955 Result := '''''';
19956 exit;
19957 end;
19958 Strt := 1;
19959 for I := 1 to Length( S ) + 1 do
19960 begin
19961 if (I > Length( S )) or (S[ I ] < ' ') then
19962 begin
19963 if (I > Strt) and (I > 1) then
19964 begin
19965 if Result <> '' then
19966 Result := Result + '+';
19967 Result := Result + '''' + String2DoubleQuotas( Copy( S, Strt, I - Strt ) ) + '''';
19968 end;
19969 if I > Length( S ) then break;
19970 if Result <> '' then
19971 Result := Result + '+'
19972 else
19973 Result := Result + '''''+';
19974 Result := Result + '#' + Int2Str( Integer( S[ I ] ) );
19975 Strt := I + 1;
19976 end;
19977 end;
19978 end;
19980 //[function CompareMem]
19981 function CompareMem(P1, P2: Pointer; Length: Integer): Boolean; assembler;
19983 {$IFDEF F_P}
19984 MOV EAX, [P1]
19985 MOV EDX, [P2]
19986 MOV ECX, [Length]
19987 {$ENDIF}
19988 PUSH ESI
19989 PUSH EDI
19990 MOV ESI,P1
19991 MOV EDI,P2
19992 MOV EDX,ECX
19993 XOR EAX,EAX
19994 AND EDX,3
19995 SHR ECX,1
19996 SHR ECX,1
19997 REPE CMPSD
19998 JNE @@2
19999 MOV ECX,EDX
20000 REPE CMPSB
20001 JNE @@2
20002 @@1: INC EAX
20003 @@2: POP EDI
20004 POP ESI
20005 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
20007 //[FUNCTION AllocMem]
20008 {$IFDEF ASM_VERSION}
20009 function AllocMem( Size : Integer ) : Pointer;
20010 asm //cmd //opd
20011 TEST EAX, EAX
20012 JZ @@exit
20013 PUSH EAX
20014 CALL System.@GetMem
20015 POP EDX
20016 PUSH EAX
20017 MOV CL, 0
20018 CALL System.@FillChar
20019 POP EAX
20020 @@exit:
20021 end;
20022 {$ELSE ASM_VERSION} //Pascal
20023 function AllocMem( Size : Integer ) : Pointer;
20024 begin
20025 Result := nil;
20026 if Size > 0 then
20027 begin
20028 GetMem( Result, Size );
20029 FillChar( Result^, Size, 0 );
20030 end;
20031 end;
20032 {$ENDIF ASM_VERSION}
20033 //[END AllocMem]
20035 //[procedure DisposeMem]
20036 procedure DisposeMem( var Addr : Pointer );
20037 begin
20038 if Addr <> nil then
20039 FreeMem( Addr );
20040 Addr := nil;
20041 end;
20043 //[function AnsiUpperCase]
20044 function AnsiUpperCase(const S: string): string;
20046 Len: Integer;
20047 begin
20048 Len := Length(S);
20049 SetString(Result, PChar(S), Len);
20050 if Len > 0 then CharUpperBuff(Pointer(Result), Len);
20051 end;
20053 //[function AnsiLowerCase]
20054 function AnsiLowerCase(const S: string): string;
20056 Len: Integer;
20057 begin
20058 Len := Length(S);
20059 SetString(Result, PChar(S), Len);
20060 if Len > 0 then CharLowerBuff(Pointer(Result), Len);
20061 end;
20063 {$IFNDEF _D2}
20064 {$IFNDEF _FPC}
20065 //[function WAnsiUpperCase]
20066 function WAnsiUpperCase(const S: WideString): WideString;
20067 var Len: Integer;
20068 begin
20069 Len := Length(S);
20070 Result := S;
20071 if Len > 0 then CharUpperBuffW(Pointer(Result), Len);
20072 end;
20074 //[function WAnsiLowerCase]
20075 function WAnsiLowerCase(const S: WideString): WideString;
20076 var Len: Integer;
20077 begin
20078 Len := Length(S);
20079 Result := S;
20080 if Len > 0 then CharLowerBuffW(Pointer(Result), Len);
20081 end;
20082 {$ENDIF _FPC}
20083 {$ENDIF _D2}
20085 //[function AnsiCompareStr]
20086 function AnsiCompareStr(const S1, S2: string): Integer;
20087 begin
20088 Result := CompareString(LOCALE_USER_DEFAULT, 0, PChar(S1), -1,
20089 PChar(S2), -1 ) - 2;
20090 end;
20092 //[function _AnsiCompareStr]
20093 function _AnsiCompareStr(S1, S2: PChar): Integer;
20094 begin
20095 Result := CompareString( LOCALE_USER_DEFAULT, 0, S1, -1,
20096 S2, -1) - 2;
20097 end;
20099 //[function AnsiCompareStrNoCase]
20100 function AnsiCompareStrNoCase(const S1, S2: string): Integer;
20101 begin
20102 Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, PChar(S1), -1,
20103 PChar(S2), -1 ) - 2;
20104 end;
20106 //[function _AnsiCompareStrNoCase]
20107 function _AnsiCompareStrNoCase(S1, S2: PChar): Integer;
20108 begin
20109 Result := CompareString( LOCALE_USER_DEFAULT, NORM_IGNORECASE, S1, -1,
20110 S2, -1) - 2;
20111 end;
20113 //[function AnsiCompareText]
20114 function AnsiCompareText( const S1, S2: String ): Integer;
20115 begin
20116 Result := AnsiCompareStrNoCase( S1, S2 );
20117 end;
20119 //[function StrLCopy]
20120 function StrLCopy(Dest: PChar; const Source: PChar; MaxLen: Cardinal): PChar; assembler;
20122 {$IFDEF F_P}
20123 MOV EAX, [Dest]
20124 MOV EDX, [Source]
20125 MOV ECX, [MaxLen]
20126 {$ENDIF F_P}
20127 PUSH EDI
20128 PUSH ESI
20129 PUSH EBX
20130 MOV ESI,EAX
20131 MOV EDI,EDX
20132 MOV EBX,ECX
20133 XOR AL,AL
20134 TEST ECX,ECX
20135 JZ @@1
20136 REPNE SCASB
20137 JNE @@1
20138 INC ECX
20139 @@1: SUB EBX,ECX
20140 MOV EDI,ESI
20141 MOV ESI,EDX
20142 MOV EDX,EDI
20143 MOV ECX,EBX
20144 SHR ECX,2
20145 REP MOVSD
20146 MOV ECX,EBX
20147 AND ECX,3
20148 REP MOVSB
20149 STOSB
20150 MOV EAX,EDX
20151 POP EBX
20152 POP ESI
20153 POP EDI
20154 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
20156 //[FUNCTION StrPCopy]
20157 {$IFDEF ASM_VERSION}
20158 function StrPCopy(Dest: PChar; const Source: string): PChar;
20160 PUSH EAX
20161 MOV EAX, EDX
20162 CALL System.@LStrLen
20163 MOV ECX, EAX
20164 POP EAX
20165 CALL EDX2PChar
20166 CALL StrLCopy
20167 end;
20168 {$ELSE ASM_VERSION} //Pascal
20169 function StrPCopy(Dest: PChar; const Source: string): PChar;
20170 begin
20171 Result := StrLCopy(Dest, PChar(Source), Length(Source));
20172 end;
20173 {$ENDIF ASM_VERSION}
20174 //[END StrPCopy]
20176 //[FUNCTION StrEq]
20177 {$IFDEF ASM_VERSION}
20178 function StrEq( const S1, S2 : String ) : Boolean;
20180 TEST EDX, EDX
20181 JNZ @@1
20182 @@0: CMP EAX, EDX
20183 JMP @@exit
20184 @@1: TEST EAX, EAX
20185 JZ @@0
20186 MOV ECX, [EAX-4]
20187 CMP ECX, [EDX-4]
20188 JNE @@exit
20189 PUSH EAX
20190 PUSH EDX
20191 PUSH 0
20192 MOV EDX, ESP
20193 CALL LowerCase
20194 PUSH 0
20195 MOV EAX, [ESP + 8]
20196 MOV EDX, ESP
20197 CALL LowerCase
20198 POP EAX
20199 POP EDX
20200 PUSH EDX
20201 PUSH EAX
20202 CALL System.@LStrCmp
20203 MOV EAX, ESP
20204 PUSHFD
20205 XOR EDX, EDX
20206 MOV DL, 2
20207 CALL System.@LStrArrayClr
20208 POPFD
20209 POP EDX
20210 POP EDX
20211 POP EDX
20212 POP EDX
20213 @@exit:
20214 SETZ AL
20215 end;
20216 {$ELSE ASM_VERSION} //Pascal
20217 function StrEq( const S1, S2 : String ) : Boolean;
20218 begin
20219 Result := (Length( S1 ) = Length( S2 )) and
20220 (LowerCase( S1 ) = LowerCase( S2 ));
20221 end;
20222 {$ENDIF ASM_VERSION}
20223 //[END StrEq]
20225 //[FUNCTION AnsiEq]
20226 {$IFDEF ASM_VERSION}
20227 function AnsiEq( const S1, S2 : String ) : Boolean;
20229 CALL AnsiCompareStrNoCase
20230 TEST EAX, EAX
20231 SETZ AL
20232 end;
20233 {$ELSE ASM_VERSION} //Pascal
20234 function AnsiEq( const S1, S2 : String ) : Boolean;
20235 begin
20236 Result := AnsiCompareStrNoCase( S1, S2 ) = 0;
20237 end;
20238 {$ENDIF ASM_VERSION}
20239 //[END AnsiEq]
20241 {$IFNDEF _D2}
20242 {$IFNDEF _FPC}
20243 //[function WAnsiEq]
20244 function WAnsiEq( const S1, S2 : WideString ) : Boolean;
20245 begin
20246 Result := WAnsiLowerCase( S1 )=WAnsiLowerCase( S2 );
20247 end;
20248 {$ENDIF _FPC}
20249 {$ENDIF _D2}
20251 //[FUNCTION StrIn]
20252 {$IFDEF ASM_VERSION}
20253 function StrIn(const S: String; const A: array of String): Boolean;
20255 @@1:
20256 TEST ECX, ECX
20257 JL @@ret_0
20259 PUSH EDX
20260 MOV EDX, [EDX+ECX*4]
20261 DEC ECX
20263 PUSH ECX
20264 PUSH EAX
20265 CALL StrEq
20266 DEC AL
20267 POP EAX
20268 POP ECX
20270 POP EDX
20271 JNZ @@1
20273 MOV AL, 1
20276 @@ret_0:XOR EAX, EAX
20277 end;
20278 {$ELSE ASM_VERSION} //Pascal
20279 function StrIn(const S: String; const A: array of String): Boolean;
20280 var I : Integer;
20281 begin
20282 for I := Low( A ) to High( A ) do
20283 if StrEq( S, A[ I ] ) then
20284 begin
20285 Result := True;
20286 Exit;
20287 end;
20288 Result := False;
20289 end;
20290 {$ENDIF ASM_VERSION}
20291 //[END StrIn]
20293 {$IFNDEF _D2}
20294 {$IFNDEF _FPC}
20295 //[function WStrIn]
20296 function WStrIn( const S : WideString; const A : array of WideString ) : Boolean;
20297 var I : Integer;
20298 begin
20299 for I := Low( A ) to High( A ) do
20300 if WAnsiEq( S, A[ I ] ) then
20301 begin
20302 Result := True;
20303 Exit;
20304 end;
20305 Result := False;
20306 end;
20307 {$ENDIF _FPC}
20308 {$ENDIF _D2}
20310 //[function StrIs]
20311 function StrIs( const S : String; const A : array of String; var Idx: Integer ) : Boolean;
20312 var I : Integer;
20313 begin
20314 Idx := -1;
20315 for I := Low( A ) to High( A ) do
20316 if StrEq( S, A[ I ] ) then
20317 begin
20318 Idx := I;
20319 Result := True;
20320 Exit;
20321 end;
20322 Result := False;
20323 end;
20325 //[function IntIn]
20326 function IntIn( Value: Integer; const List: array of Integer ): Boolean;
20327 var I: Integer;
20328 begin
20329 Result := FALSE;
20330 for I := 0 to High( List ) do
20331 begin
20332 if Value = List[ I ] then
20333 begin
20334 Result := TRUE;
20335 break;
20336 end;
20337 end;
20338 end;
20340 //[FUNCTION _StrSatisfy]
20341 {$IFDEF ASM_VERSION}
20342 function _StrSatisfy( S, Mask : PChar ) : Boolean;
20344 TEST EAX, EAX
20345 JZ @@exit
20346 XCHG ECX, EAX
20347 // EDX <- Mask
20348 // ECX <- S
20349 XOR EAX, EAX
20350 MOV AL, '*'
20351 @@rest_satisfy:
20352 PUSH ECX
20353 PUSH EDX
20355 @@nx_char:
20356 MOV AH, [EDX]
20357 OR AH, [ECX]
20358 JZ @@fin //@@ret_true
20360 MOV AH, 0
20362 CMP word ptr [EDX], AX //'*'
20363 JE @@fin //@@ret_true
20365 CMP byte ptr [ECX], AH
20366 JNE @@10
20368 DEC EDX
20369 @@1:
20370 INC EDX
20371 CMP byte ptr [EDX], AL //'*'
20372 JE @@1
20373 //CMP byte ptr [EDX], '?'
20374 //JE @@1
20376 CMP byte ptr [EDX], AH
20377 SETZ AL
20378 JMP @@fin
20380 @@10: CMP byte ptr [EDX], AH
20381 JE @@ret_false
20383 CMP byte ptr [EDX], '?'
20384 JNE @@11
20386 @@go_nx_char:
20387 INC ECX
20388 INC EDX
20389 JMP @@nx_char
20391 @@11:
20392 CMP byte ptr [EDX], AL //'*'
20393 JNE @@20
20395 INC EDX
20396 @@12: CMP byte ptr [ECX], AH
20397 JE @@ret_false
20399 CALL @@rest_satisfy
20400 TEST AL, AL
20401 JNE @@fin
20402 MOV AL, '*'
20404 INC ECX
20405 JMP @@12
20407 @@20: MOV AH, [EDX]
20408 XOR AH, [ECX]
20410 JE @@go_nx_char
20411 @@ret_false:
20412 XOR EAX, EAX
20414 @@fin:
20415 POP EDX
20416 POP ECX
20417 @@exit:
20418 end;
20419 {$ELSE ASM_VERSION} //Pascal
20420 function _StrSatisfy( S, Mask : PChar ) : Boolean;
20421 label next_char;
20422 begin
20423 next_char:
20424 Result := True;
20425 if (S^ = #0) and (Mask^ = #0) then exit;
20426 if (Mask^ = '*') and (Mask[1] = #0) then exit;
20427 if S^ = #0 then
20428 begin
20429 while Mask^ = '*' do
20430 Inc( Mask );
20431 Result := Mask^ = #0;
20432 exit;
20433 end;
20434 Result := False;
20435 if Mask^ = #0 then exit;
20436 if Mask^ = '?' then
20437 begin
20438 Inc( S ); Inc( Mask ); goto next_char;
20439 end;
20440 if Mask^ = '*' then
20441 begin
20442 Inc( Mask );
20443 while S^ <> #0 do
20444 begin
20445 Result := _StrSatisfy( S, Mask );
20446 if Result then exit;
20447 Inc( S );
20448 end;
20449 exit; // (Result = False)
20450 end;
20451 Result := S^ = Mask^;
20452 Inc( S ); Inc( Mask );
20453 if Result then goto next_char;
20454 end;
20455 {$ENDIF ASM_VERSION}
20456 //[END _StrSatisfy]
20458 //[FUNCTION StrSatisfy]
20459 {$IFDEF ASM_VERSION}
20460 function StrSatisfy( const S, Mask: String ): Boolean;
20462 PUSH ESI
20463 XCHG ESI, EAX
20464 PUSH 0
20465 XCHG EAX, EDX
20466 CALL EAX2PChar
20467 MOV EDX, ESP
20469 CMP byte ptr [EAX], 0
20470 JZ @@0
20471 CALL AnsiLowerCase
20472 @@0:
20473 XCHG EAX, ESI
20474 PUSH 0
20475 CALL EAX2PChar
20476 MOV EDX, ESP
20478 CMP byte ptr [EAX], 0
20479 JZ @@1
20480 CALL AnsiLowerCase
20481 @@1:
20482 POP EAX
20483 POP EDX
20484 PUSH EDX
20485 PUSH EAX
20486 CALL _StrSatisfy
20488 XCHG ESI, EAX
20490 CALL RemoveStr
20491 CALL RemoveStr
20492 XCHG EAX, ESI
20494 POP ESI
20495 end;
20496 {$ELSE ASM_VERSION} //Pascal
20497 function StrSatisfy( const S, Mask: String ): Boolean;
20498 begin
20499 Result := _StrSatisfy( PChar( AnsiLowerCase( S ) ),
20500 PChar( AnsiLowerCase( Mask ) ) );
20501 end;
20502 {$ENDIF ASM_VERSION}
20503 //[END StrSatisfy]
20505 //[FUNCTION _2StrSatisfy]
20506 {$IFDEF ASM_VERSION}
20507 function _2StrSatisfy( S, Mask: PChar ): Boolean;
20508 asm // //
20509 PUSH EBX
20510 XCHG EBX, EAX
20511 PUSH 0
20512 MOV EAX, ESP
20513 CALL System.@LStrFromPChar
20514 PUSH 0
20515 MOV EAX, ESP
20516 MOV EDX, EBX
20517 CALL System.@LStrFromPChar
20518 POP EAX
20519 POP EDX
20520 PUSH EDX
20521 PUSH EAX
20522 CALL StrSatisfy
20523 XCHG EBX, EAX
20524 CALL RemoveStr
20525 CALL RemoveStr
20526 XCHG EAX, EBX
20527 POP EBX
20528 end;
20529 {$ELSE ASM_VERSION} // Pascal
20530 function _2StrSatisfy( S, Mask: PChar ): Boolean;
20531 begin
20532 Result := StrSatisfy( S, Mask );
20533 end;
20534 {$ENDIF ASM_VERSION}
20535 //[END _2StrSatisfy]
20537 //[function StrReplace]
20538 function StrReplace( var S: String; const From, ReplTo: String ): Boolean;
20539 var I: Integer;
20540 begin
20541 I := pos( From, S );
20542 if I > 0 then
20543 begin
20544 S := Copy( S, 1, I - 1 ) + ReplTo + CopyEnd( S, I + Length( From ) );
20545 Result := TRUE;
20547 else Result := FALSE;
20548 end;
20551 {$IFDEF _FPC}
20552 //[procedure SetLengthW]
20553 procedure SetLengthW( var W: WideString; NewLength: Integer );
20554 begin
20555 while Length( W ) < NewLength do
20556 W := W + ' ' + W;
20557 if Length( W ) > NewLength then
20558 Delete( W, NewLength + 1, Length( W ) - NewLength );
20559 end;
20561 //[function CopyW]
20562 function CopyW( const W: WideString; From, Count: Integer ): WideString;
20563 begin
20564 Result := '';
20565 if Count <= 0 then Exit;
20566 SetLengthW( Result, Count );
20567 Move( W[ From ], Result[ 1 ], Count * Sizeof( WideChar ) );
20568 end;
20570 //[function posW]
20571 function posW( const S1, S2: String ): Integer;
20572 var I, L1: Integer;
20573 begin
20574 L1 := Length( S1 );
20575 for I := 1 to Length( S2 )-L1+1 do
20576 begin
20577 if Copy( S2, I, L1 ) = S1 then
20578 begin
20579 Result := I;
20580 Exit;
20581 end;
20582 end;
20583 Result := 0;
20584 end;
20585 {$ENDIF _FPC}
20587 {$IFNDEF _FPC}
20588 {$IFNDEF _D2}
20589 //[function WStrReplace]
20590 function WStrReplace( var S: WideString; const From, ReplTo: WideString ): Boolean;
20591 var I: Integer;
20592 begin
20593 I := pos( From, S );
20594 if I > 0 then
20595 begin
20596 S := Copy( S, 1, I - 1 ) + ReplTo + Copy( S, I + Length( From ), MaxInt );
20597 Result := TRUE;
20599 else Result := FALSE;
20600 end;
20602 //[function WStrRepeat]
20603 function WStrRepeat( const S: WideString; Count: Integer ): WideString;
20604 var I, L: Integer;
20605 begin
20606 L := Length( S );
20607 SetLength( Result, L * Count );
20608 for I := 0 to Count-1 do
20609 Move( S[ 1 ], Result[ 1 + I * L ], L * Sizeof( WideChar ) );
20610 end;
20611 {$ENDIF _D2}
20612 {$ENDIF _FPC}
20615 //[function StrRepeat]
20616 function StrRepeat( const S: String; Count: Integer ): String;
20617 var I, L: Integer;
20618 begin
20619 L := Length( S );
20620 SetLength( Result, L * Count );
20621 for I := 0 to Count-1 do
20622 Move( S[ 1 ], Result[ 1 + I * L ], L );
20623 end;
20626 //[PROCEDURE NormalizeUnixText]
20627 {$IFDEF ASM_VERSION}
20628 procedure NormalizeUnixText( var S: String );
20629 asm //cmd //opd
20630 CMP dword ptr [EAX], 0
20631 JZ @@exit
20632 PUSH EBX
20633 PUSH EDI
20634 MOV EBX, EAX
20635 CALL UniqueString
20636 MOV EDI, [EBX]
20637 @@1: MOV EAX, EDI
20638 CALL System.@LStrLen
20639 XCHG ECX, EAX
20640 MOV AX, $0D0A
20642 CMP byte ptr [EDI], AL
20643 JNE @@loo
20644 MOV byte ptr [EDI], AH
20645 @@loo:
20646 TEST ECX, ECX
20647 JZ @@fin
20648 @@loo1:
20649 REPNZ SCASB
20650 JNZ @@fin
20651 CMP byte ptr [EDI-2], AH
20652 JE @@loo
20653 MOV byte ptr [EDI-1], AH
20654 JNE @@loo1
20655 @@fin: POP EDI
20656 POP EBX
20657 @@exit:
20658 end;
20659 {$ELSE ASM_VERSION} //Pascal
20660 procedure NormalizeUnixText( var S: String );
20661 var I: Integer;
20662 begin
20663 if S <> '' then
20664 begin
20665 if S[ 1 ] = #10 then
20666 S[ 1 ] := #13;
20667 for I := 2 to Length(S) do
20668 if (S[I]=#10) and (S[I-1]<>#13) then
20669 S[I] := #13;
20670 end;
20671 end;
20672 {$ENDIF ASM_VERSION}
20673 //[END NormalizeUnixText]
20675 //[function StrComp]
20676 function StrComp(const Str1, Str2: PChar): Integer; assembler;
20678 {$IFDEF F_P}
20679 MOV EAX, [Str1]
20680 MOV EDX, [Str2]
20681 {$ENDIF F_P}
20682 PUSH EDI
20683 PUSH ESI
20684 MOV EDI,EDX
20685 XCHG ESI,EAX
20686 OR ECX, -1
20687 XOR EAX,EAX
20688 REPNE SCASB
20689 NOT ECX
20690 MOV EDI,EDX
20691 XOR EDX,EDX
20692 REPE CMPSB
20693 MOV AL,[ESI-1]
20694 MOV DL,[EDI-1]
20695 SUB EAX,EDX
20696 POP ESI
20697 POP EDI
20698 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
20700 function StrComp_NoCase(const Str1, Str2: PChar): Integer;
20702 {$IFDEF F_P}
20703 MOV EAX, [Str1]
20704 MOV EDX, [Str2]
20705 {$ENDIF F_P}
20706 PUSH EDI
20707 PUSH ESI
20708 MOV EDI,EDX
20709 XCHG ESI,EAX
20710 OR ECX, -1
20711 XOR EAX,EAX
20712 REPNE SCASB
20714 NOT ECX
20715 MOV EDI,EDX
20716 @@0:
20717 XOR EDX,EDX
20718 REPE CMPSB
20719 MOV AL,[ESI-1]
20720 MOV AH, AL
20721 SUB AH, 'a'
20722 CMP AH, 25
20723 JA @@1
20724 SUB AL, $20
20725 @@1:
20726 MOV DL,[EDI-1]
20727 MOV AH, DL
20728 SUB AH, 'a'
20729 CMP AH, 25
20730 JA @@2
20731 SUB DL, $20
20732 @@2:
20733 MOV AH, 0
20734 SUB EAX,EDX
20735 JNZ @@exit
20736 CMP DL, 0
20737 JNZ @@0
20739 @@exit:
20740 POP ESI
20741 POP EDI
20742 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
20744 //[function StrLComp_NoCase]
20745 function StrLComp_NoCase(const Str1, Str2: PChar; MaxLen: Cardinal): Integer;
20747 {$IFDEF F_P}
20748 MOV EAX, [Str1]
20749 MOV EDX, [Str2]
20750 MOV ECX, [MaxLen]
20751 {$ENDIF F_P}
20752 PUSH EDI
20753 PUSH ESI
20754 PUSH EBX
20755 MOV EDI,EDX
20756 MOV ESI,EAX
20757 MOV EBX,ECX
20758 XOR EAX,EAX
20759 OR ECX,ECX
20760 JE @@exit
20761 REPNE SCASB
20762 SUB EBX,ECX
20763 MOV ECX,EBX
20764 MOV EDI,EDX
20765 @@0:
20766 XOR EDX,EDX
20767 REPE CMPSB
20768 MOV AL,[ESI-1]
20769 MOV AH, AL
20770 SUB AH, 'a'
20771 CMP AH, 25
20772 JA @@1
20773 SUB AL, $20
20774 @@1:
20775 MOV DL,[EDI-1]
20776 MOV AH, DL
20777 SUB AH, 'a'
20778 CMP AH, 25
20779 JA @@2
20780 SUB DL, $20
20781 @@2:
20782 MOV AH, 0
20783 SUB EAX,EDX
20784 JECXZ @@exit
20785 JZ @@0
20787 @@exit:
20788 POP EBX
20789 POP ESI
20790 POP EDI
20791 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
20793 //[function StrLComp]
20794 function StrLComp(const Str1, Str2: PChar; MaxLen: Cardinal): Integer; assembler;
20796 {$IFDEF F_P}
20797 MOV EAX, [Str1]
20798 MOV EDX, [Str2]
20799 MOV ECX, [MaxLen]
20800 {$ENDIF F_P}
20801 PUSH EDI
20802 PUSH ESI
20803 PUSH EBX
20804 MOV EDI,EDX
20805 MOV ESI,EAX
20806 MOV EBX,ECX
20807 XOR EAX,EAX
20808 OR ECX,ECX
20809 JE @@1
20810 REPNE SCASB
20811 SUB EBX,ECX
20812 MOV ECX,EBX
20813 MOV EDI,EDX
20814 XOR EDX,EDX
20815 REPE CMPSB
20816 MOV AL,[ESI-1]
20817 MOV DL,[EDI-1]
20818 SUB EAX,EDX
20819 @@1: POP EBX
20820 POP ESI
20821 POP EDI
20822 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
20824 //[function StrLen]
20825 function StrLen(const Str: PChar): Cardinal; assembler;
20827 {$IFDEF F_P}
20828 MOV EAX, [Str]
20829 {$ENDIF F_P}
20830 XCHG EAX, EDI
20831 XCHG EDX, EAX
20832 OR ECX, -1
20833 XOR EAX, EAX
20834 CMP EAX, EDI
20835 JE @@exit0
20836 REPNE SCASB
20837 DEC EAX
20838 DEC EAX
20839 SUB EAX,ECX
20840 @@exit0:
20841 MOV EDI,EDX
20842 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
20844 //[FUNCTION __DelimiterLast]
20845 {$IFDEF ASM_VERSION}
20846 function __DelimiterLast( Str: PChar; Delimiters: PChar ): PChar;
20848 PUSH ESI
20850 CALL EAX2PChar
20852 MOV ESI, EDX
20853 MOV EDX, EAX
20855 @@tolast:
20856 CMP byte ptr [EAX], 0
20857 JZ @@next1
20858 INC EAX
20859 JMP @@tolast
20861 @@next1:
20862 PUSH EAX
20864 @@next:
20865 LODSB
20866 TEST AL, AL
20867 JZ @@exit
20869 PUSH EDX
20870 XCHG EDX, EAX
20871 CALL StrRScan
20872 POP EDX
20874 TEST EAX, EAX
20875 JZ @@next
20877 POP ECX
20878 CMP byte ptr [ECX], 0
20879 JZ @@next1
20881 CMP EAX, ECX
20882 JG @@next1
20884 PUSH ECX
20885 JLE @@next
20887 @@exit: POP EAX
20888 POP ESI
20889 end;
20890 {$ELSE ASM_VERSION} //Pascal
20891 function __DelimiterLast( Str: PChar; Delimiters: PChar ): PChar;
20893 P, F : PChar;
20894 begin
20895 P := Str;
20896 Result := P + StrLen( Str );
20897 while Delimiters^ <> #0 do
20898 begin
20899 F := StrRScan( P, Delimiters^ );
20900 if F <> nil then
20901 if (Result^ = #0) or (Integer(F) > Integer(Result)) then
20902 Result := F;
20903 Inc( Delimiters );
20904 end;
20905 end;
20906 {$ENDIF ASM_VERSION}
20907 //[END __DelimiterLast]
20909 //[function SkipSpaces]
20910 function SkipSpaces( P: PChar ): PChar;
20911 begin
20912 while True do
20913 begin
20914 while (P[0] <> #0) and (P[0] <= ' ') do Inc(P);
20915 if (P[0] = '"') and (P[1] = '"') then Inc(P, 2) else Break;
20916 end;
20917 Result := P;
20918 end;
20920 //[function SkipParam]
20921 function SkipParam(P: PChar): PChar;
20922 begin
20923 P := SkipSpaces( P );
20924 while P[0] > ' ' do
20925 if P[0] = '"' then
20926 begin
20927 Inc(P);
20928 while (P[0] <> #0) and (P[0] <> '"') do
20929 Inc(P);
20930 if P[0] <> #0 then Inc(P);
20932 else
20933 Inc(P);
20934 Result := P;
20935 end;
20937 //[FUNCTION ParamStr]
20938 function ParamStr( Idx: Integer ): String;
20940 P, P1: PChar;
20941 Buffer: array[ 0..260 ] of Char;
20942 begin
20943 if Idx = 0 then
20944 SetString( Result, Buffer, GetModuleFileName( 0, Buffer, Sizeof( Buffer ) ) )
20945 else
20946 begin
20947 P := GetCommandLine;
20948 repeat
20949 P := SkipSpaces( P );
20950 P1 := P;
20951 P := SkipParam(P);
20952 if Idx = 0 then Break;
20953 Dec(Idx);
20954 until (Idx < 0) or (P = P1);
20955 Result := Copy( P1, 1, P - P1 );
20956 if Length( Result ) >= 2 then
20957 if (Result[ 1 ] = '"') and (Result[ Length( Result ) ] = '"') then
20958 Result := Copy( Result, 2, Length( Result ) - 2 );
20959 end;
20960 end;
20961 //[END ParamStr]
20963 //[FUNCTION ParamCount]
20964 function ParamCount: Integer;
20966 S: string;
20967 begin
20968 Result := 0;
20969 while True do
20970 begin
20971 S := ParamStr(Result + 1);
20972 if S = '' then Break;
20973 Inc(Result);
20974 end;
20975 end;
20976 //[END ParamCount]
20978 //[FUNCTION DelimiterLast]
20979 {$IFDEF ASM_VERSION}
20980 function DelimiterLast( const Str, Delimiters: String ): Integer;
20982 CALL EAX2PChar
20983 CALL EDX2PChar
20984 PUSH EAX
20985 CALL __DelimiterLast
20986 POP EDX
20987 SUB EAX, EDX
20988 INC EAX
20989 end;
20990 {$ELSE ASM_VERSION} //Pascal
20991 function DelimiterLast( const Str, Delimiters: String ): Integer;
20992 var PStr: PChar;
20993 begin
20994 PStr := PChar( Str );
20995 Result := Integer( __DelimiterLast( PStr, PChar( Delimiters ) ) )
20996 - Integer( PStr )
20997 + 1; // {Viman}
20998 end;
20999 {$ENDIF ASM_VERSION}
21000 //[END DelimiterLast]
21002 // Thanks to Marco Bobba - Marisa Bo for this code
21003 //[function StrIsStartingFrom]
21004 function StrIsStartingFrom( Str, Pattern: PChar ): Boolean;
21006 {$IFDEF F_P}
21007 MOV EAX, [Str]
21008 MOV EDX, [Pattern]
21009 {$ENDIF F_P}
21010 XOR ECX, ECX
21011 @@1:
21012 MOV CL, [EDX] // pattern[ i ]
21013 INC EDX
21014 MOV CH, [EAX] // str[ i ]
21015 INC EAX
21016 JECXZ @@2 // str = pattern; CL = #0, CH = #0
21017 CMP CL, CH
21018 JE @@1
21019 @@2:
21020 TEST CL, CL
21021 SETZ AL
21022 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
21024 function StrIsStartingFromNoCase( Str, Pattern: PChar ): Boolean;
21026 {$IFDEF F_P}
21027 MOV EAX, [Str]
21028 MOV EDX, [Pattern]
21029 {$ENDIF F_P}
21030 XOR ECX, ECX
21031 @@1:
21032 MOV CL, [EDX] // pattern[ i ]
21033 INC EDX
21034 MOV CH, [EAX] // str[ i ]
21035 INC EAX
21036 JECXZ @@2 // str = pattern; CL = #0, CH = #0
21037 CMP CL, 'a'
21038 JB @@cl_ok
21039 CMP CL, 'z'
21040 JA @@cl_ok
21041 SUB CL, 32
21042 @@cl_ok:
21043 CMP CH, 'a'
21044 JB @@ch_ok
21045 CMP CH, 'z'
21046 JA @@ch_ok
21047 SUB CH, 32
21048 @@ch_ok:
21049 CMP CL, CH
21050 JE @@1
21051 @@2:
21052 TEST CL, CL
21053 SETZ AL
21054 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
21056 {$IFNDEF _FPC}
21057 //[FUNCTION Format]
21058 {$IFDEF ASM_VERSION}
21059 function Format( const fmt: string; params: array of const ): String;
21061 PUSH ESI
21062 PUSH EDI
21063 PUSH EBX
21064 MOV EBX, ESP
21065 ADD ESP, -2048
21066 MOV ESI, ESP
21068 INC ECX
21069 JZ @@2
21070 @@1:
21071 MOV EDI, [EDX + ECX*8 - 8]
21072 PUSH EDI
21073 LOOP @@1
21074 @@2:
21075 PUSH ESP
21076 PUSH EAX
21077 PUSH ESI
21079 CALL wvsprintf
21081 MOV EDX, ESI
21082 MOV EAX, @Result
21083 CALL System.@LStrFromPChar
21085 MOV ESP, EBX
21086 POP EBX
21087 POP EDI
21088 POP ESI
21089 end;
21090 {$ELSE ASM_VERSION} //Pascal
21091 function Format( const fmt: string; params: array of const ): String;
21092 var Buffer: array[ 0..2047 ] of Char;
21093 ElsArray, El: PDWORD;
21094 I : Integer;
21095 P : PDWORD;
21096 begin
21097 ElsArray := nil;
21098 if High( params ) >= 0 then
21099 GetMem( ElsArray, (High( params ) + 1) * sizeof( Pointer ) );
21100 El := ElsArray;
21101 for I := 0 to High( params ) do
21102 begin
21103 P := @params[ I ];
21104 P := Pointer( P^ );
21105 El^ := DWORD( P );
21106 Inc( El );
21107 end;
21108 wvsprintf( @Buffer[0], PChar( fmt ), PChar( ElsArray ) );
21109 Result := Buffer;
21110 if ElsArray <> nil then
21111 FreeMem( ElsArray );
21112 end;
21113 {$ENDIF ASM_VERSION}
21114 //[END Format]
21116 //[function LStrFromPWCharLen]
21117 function LStrFromPWCharLen(Source: PWideChar; Length: Integer): String;
21119 DestLen: Integer;
21120 Buffer: array[0..2047] of Char;
21121 begin
21122 if Length <= 0 then
21123 begin
21124 //_LStrClr(Result);
21125 Result := '';
21126 Exit;
21127 end;
21128 if Length < SizeOf(Buffer) div 2 then
21129 begin
21130 DestLen := WideCharToMultiByte(0, 0, Source, Length,
21131 Buffer, SizeOf(Buffer), nil, nil);
21132 if DestLen > 0 then
21133 begin
21134 Result := Buffer;
21135 //System.LStrFromPCharLen(Result, Buffer, DestLen);
21136 Exit;
21137 end;
21138 end;
21139 DestLen := WideCharToMultiByte(0, 0, Source, Length, nil, 0, nil, nil);
21140 // _LStrFromPCharLen(Dest, nil, DestLen);
21141 SetLength( Result, DestLen );
21142 WideCharToMultiByte(0, 0, Source, Length, Pointer(Result), DestLen, nil, nil);
21143 end;
21145 //[function LStrFromPWChar]
21146 function LStrFromPWChar(Source: PWideChar): String;
21147 {* from Delphi5 - because D2 does not contain it. }
21149 PUSH EDX
21150 XOR EDX,EDX
21151 TEST EAX,EAX
21152 JE @@5
21153 PUSH EAX
21154 @@0: CMP DX,[EAX+0]
21155 JE @@4
21156 CMP DX,[EAX+2]
21157 JE @@3
21158 CMP DX,[EAX+4]
21159 JE @@2
21160 CMP DX,[EAX+6]
21161 JE @@1
21162 ADD EAX,8
21163 JMP @@0
21164 @@1: ADD EAX,2
21165 @@2: ADD EAX,2
21166 @@3: ADD EAX,2
21167 @@4: XCHG EDX,EAX
21168 POP EAX
21169 SUB EDX,EAX
21170 SHR EDX,1
21171 @@5: POP ECX
21172 JMP LStrFromPWCharLen
21173 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
21174 {$ENDIF _FPC}
21177 /////////////////////////////////////////////////////////////////////////
21180 // F I L E S
21183 /////////////////////////////////////////////////////////////////////////
21184 //[FILES]
21186 This part of the unit modified by Tim Slusher and Vladimir Kladov.
21189 {* Set of utility methods to work with files
21190 and reqistry.
21191 When programming KOL, which is Windows API-oriented, You should
21192 avoid alien (for Windows) embedded Pascal files handling, and
21193 use API-calls which implemented very well. This set of functions
21194 is intended to make this easier.
21195 Also TDirList object implementation present here and some registry
21196 access functions, which allow to make code more elegant.
21199 {$UNDEF ASM_LOCAL}
21200 {$IFDEF ASM_VERSION}
21201 {$DEFINE ASM_LOCAL}
21202 {$ENDIF ASM_VERSION}
21204 //[FUNCTION FileCreate]
21205 {$IFDEF ASM_VERSION}
21206 function FileCreate( const FileName: string; OpenFlags: DWord): THandle;
21208 XOR ECX, ECX
21209 PUSH ECX
21210 MOV ECX, EDX
21211 SHR ECX, 16
21212 AND CX, $1FFF
21213 JNZ @@1
21214 MOV CL, FILE_ATTRIBUTE_NORMAL
21215 @@1: PUSH ECX
21216 MOV CL, DH
21217 PUSH ECX // CreationMode
21218 PUSH 0
21219 MOV CL, DL
21220 PUSH ECX // ShareMode
21221 MOV DX, 0
21222 PUSH EDX // AccessMode
21223 //CALL System.@LStrToPChar // FileName must not be ''
21224 PUSH EAX
21225 CALL CreateFile
21226 end;
21227 {$ELSE ASM_VERSION} //Pascal
21228 function FileCreate(const FileName: string; OpenFlags: DWord): THandle;
21229 var Attr: DWORD;
21230 begin
21231 Attr := (OpenFlags shr 16) and $1FFF;
21232 if Attr = 0 then Attr := FILE_ATTRIBUTE_NORMAL;
21233 Result := CreateFile( PChar(FileName), OpenFlags and $F0000000,
21234 OpenFlags and $F, nil, (OpenFlags shr 8) and $F,
21235 Attr, 0 );
21236 end;
21237 {$ENDIF ASM_VERSION}
21238 //[END FileCreate]
21240 //[FUNCTION FileClose]
21241 {$IFDEF ASM_VERSION}
21242 function FileClose( Handle: THandle): Boolean;
21244 PUSH EAX
21245 CALL CloseHandle
21246 TEST EAX, EAX
21247 SETNZ AL
21248 end;
21249 {$ELSE ASM_VERSION} //Pascal
21250 function FileClose(Handle: THandle): boolean;
21251 begin
21252 Result := CloseHandle(Handle);
21253 end;
21254 {$ENDIF ASM_VERSION}
21255 //[END FileClose]
21257 //[FUNCTION FileExists]
21258 {$IFDEF ASM_VERSION}
21259 function FileExists( const FileName : String ) : Boolean;
21260 const size_TWin32FindData = sizeof( TWin32FindData );
21262 CALL EAX2PChar
21263 PUSH EAX
21264 CALL GetFileAttributes
21265 INC EAX
21266 JZ @@exit
21267 DEC EAX
21268 {$IFDEF PARANOIA}
21269 DB $24, FILE_ATTRIBUTE_DIRECTORY
21270 {$ELSE}
21271 AND AL, FILE_ATTRIBUTE_DIRECTORY
21272 {$ENDIF}
21273 SETZ AL
21274 @@exit:
21275 end;
21276 {$ELSE ASM_VERSION} //Pascal
21277 function FileExists( const FileName : String ) : Boolean;
21279 Code: Integer;
21280 begin
21281 Code := GetFileAttributes(PChar(FileName));
21282 Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code = 0);
21283 end;
21284 {$ENDIF ASM_VERSION}
21285 //[END FileExists]
21287 //[FUNCTION FileSeek]
21288 {$IFDEF ASM_VERSION}
21289 function FileSeek( Handle: THandle; MoveTo: integer; MoveMethod: TMoveMethod): DWord;
21291 MOVZX ECX, CL
21292 PUSH ECX
21293 PUSH 0
21294 PUSH EDX
21295 PUSH EAX
21296 CALL SetFilePointer
21297 end;
21298 {$ELSE ASM_VERSION} //Pascal
21299 function FileSeek(Handle: THandle; MoveTo: integer; MoveMethod: TMoveMethod): DWord;
21300 begin
21301 Result := SetFilePointer(Handle, MoveTo, nil, Ord( MoveMethod ) );
21302 end;
21303 {$ENDIF ASM_VERSION}
21304 //[END FileSeek]
21306 //[FUNCTION FileRead]
21307 {$IFDEF ASM_VERSION}
21308 function FileRead( Handle: THandle; var Buffer; Count: DWord): DWord;
21310 PUSH EBP
21311 PUSH 0
21312 MOV EBP, ESP
21313 PUSH 0
21314 PUSH EBP
21315 PUSH ECX
21316 PUSH EDX
21317 PUSH EAX
21318 CALL ReadFile
21319 TEST EAX, EAX
21320 POP EAX
21321 JNZ @@exit
21322 XOR EAX, EAX
21323 @@exit:
21324 POP EBP
21325 end;
21326 {$ELSE ASM_VERSION} //Pascal
21327 function FileRead(Handle: THandle; var Buffer; Count: DWord): DWord;
21328 begin
21329 if not ReadFile(Handle, Buffer, Count, Result, nil) then
21330 Result := 0;
21331 end;
21332 {$ENDIF ASM_VERSION}
21333 //[END FileRead]
21335 //[FUNCTION File2Str]
21336 {$IFDEF ASM_VERSION}
21337 function File2Str( Handle: THandle): String;
21339 PUSH EDX
21340 TEST EAX, EAX
21341 JZ @@exit // return ''
21343 PUSH EBX
21344 MOV EBX, EAX // EBX = Handle
21345 XOR EDX, EDX
21346 XOR ECX, ECX
21347 INC ECX
21348 CALL FileSeek
21349 PUSH EAX // Pos
21350 PUSH 0
21351 PUSH EBX
21352 CALL GetFileSize
21353 POP EDX
21354 SUB EAX, EDX // EAX = Size - Pos
21355 JZ @@exitEBX
21357 PUSH EAX
21358 CALL System.@GetMem
21359 XCHG EAX, EBX
21360 MOV EDX, EBX
21361 POP ECX
21362 PUSH ECX
21363 CALL FileRead
21364 POP ECX
21365 MOV EDX, EBX
21366 POP EBX
21367 POP EAX
21368 PUSH EDX
21369 {$IFDEF _D2}
21370 CALL _LStrFromPCharLen
21371 {$ELSE}
21372 CALL System.@LStrFromPCharLen
21373 {$ENDIF}
21374 JMP @@freebuf
21376 @@exitEBX:
21377 POP EBX
21378 @@exit:
21379 XCHG EDX, EAX
21380 POP EAX // @Result
21381 PUSH EDX
21382 CALL System.@LStrFromPChar
21383 @@freebuf:
21384 POP EAX
21385 TEST EAX, EAX
21386 JZ @@fin
21387 CALL System.@FreeMem
21388 @@fin:
21389 end;
21390 {$ELSE ASM_VERSION} //Pascal
21391 function File2Str(Handle: THandle): String;
21392 var Pos, Size: DWORD;
21393 begin
21394 Result := '';
21395 if Handle = 0 then Exit;
21396 Pos := FileSeek( Handle, 0, spCurrent );
21397 Size := GetFileSize( Handle, nil );
21398 SetString( Result, nil, Size - Pos + 1 );
21399 FileRead( Handle, Result[ 1 ], Size - Pos );
21400 Result[ Size - Pos + 1 ] := #0;
21401 end;
21402 {$ENDIF ASM_VERSION}
21403 //[END File2Str]
21405 //[FUNCTION FileWrite]
21406 {$IFDEF ASM_VERSION}
21407 function FileWrite( Handle: THandle; const Buffer; Count: DWord): DWord;
21409 PUSH EBP
21410 PUSH EBP
21411 MOV EBP, ESP
21412 PUSH 0
21413 PUSH EBP
21414 PUSH ECX
21415 PUSH EDX
21416 PUSH EAX
21417 CALL WriteFile
21418 TEST EAX, EAX
21419 POP EAX
21420 JNZ @@exit
21421 XOR EAX, EAX
21422 @@exit:
21423 POP EBP
21424 end;
21425 {$ELSE ASM_VERSION} //Pascal
21426 function FileWrite(Handle: THandle; const Buffer; Count: DWord): DWord;
21427 begin
21428 if not WriteFile(Handle, Buffer, Count, Result, nil) then
21429 Result := 0;
21430 end;
21431 {$ENDIF ASM_VERSION}
21432 //[END FileWrite]
21434 //[FUNCTION FileEOF]
21435 {$IFDEF ASM_VERSION}
21436 function FileEOF( Handle: THandle ) : Boolean;
21438 PUSH EAX
21440 PUSH 0
21441 PUSH EAX
21442 CALL GetFileSize
21444 XCHG EAX, [ESP]
21446 MOV CL, spCurrent
21447 XOR EDX, EDX
21448 CALL FileSeek
21450 POP EDX
21451 CMP EAX, EDX
21452 SETGE AL
21453 end;
21454 {$ELSE ASM_VERSION} //Pascal
21455 function FileEOF( Handle: THandle ) : Boolean;
21456 var Siz, Pos : DWord;
21457 begin
21458 Siz := GetFileSize( Handle, nil );
21459 Pos := FileSeek( Handle, 0, spCurrent );
21460 Result := Pos >= Siz;
21461 end;
21462 {$ENDIF ASM_VERSION}
21463 //[END FileEOF]
21465 //[FUNCTION FileFullPath]
21466 {$IFDEF ASM_noVERSION}
21467 function FileFullPath( const FileName: String ) : String;
21468 const
21469 BkSlash: String = '\';
21470 szTShFileInfo = sizeof( TShFileInfo );
21472 PUSH EBX
21473 PUSH ESI
21474 MOV EBX, EDX
21475 PUSH EAX
21477 XCHG EAX, EDX
21478 CALL System.@LStrClr
21480 POP EDX
21481 PUSH 0
21482 MOV EAX, ESP
21483 CALL System.@LStrAsg
21484 MOV ESI, ESP
21486 @@loo: CMP dword ptr [ESI], 0
21487 JZ @@fin
21489 MOV EAX, ESI
21490 MOV EDX, [BkSlash]
21491 PUSH 0
21492 MOV ECX, ESP
21493 CALL Parse
21495 CMP dword ptr [EBX], 0
21496 JE @@1
21497 MOV EAX, EBX
21498 MOV EDX, [BkSlash]
21499 CALL System.@LStrCat
21500 JMP @@2
21501 @@1:
21502 POP EAX
21503 PUSH EAX
21504 CALL System.@LStrLen
21505 CMP EAX, 2
21506 JNE @@2
21507 POP EAX
21508 PUSH EAX
21509 CMP byte ptr [EAX+1], ':'
21510 JNE @@2
21512 MOV EAX, EBX
21513 POP EDX
21514 PUSH EDX
21515 CALL System.@LStrAsg
21516 JMP @@3
21517 @@2:
21518 PUSH 0
21519 MOV EAX, ESP
21520 MOV EDX, [EBX]
21521 CALL System.@LStrAsg
21522 MOV EAX, ESP
21523 MOV EDX, [ESP+4]
21524 CALL System.@LStrCat
21525 POP EAX
21526 PUSH EAX
21527 SUB ESP, szTShFileInfo
21528 MOV EDX, ESP
21529 PUSH SHGFI_DISPLAYNAME
21530 PUSH szTShFileInfo
21531 PUSH EDX
21532 PUSH 0
21533 PUSH EAX
21534 CALL ShGetFileInfo
21535 LEA EDX, [ESP].TShFileInfo.szDisplayName
21536 CMP byte ptr [EDX], 0
21537 JE @@clr_stk
21538 LEA EAX, [ESP+szTShFileInfo+4]
21539 CALL System.@LStrFromPChar
21540 @@clr_stk:
21541 ADD ESP, szTShFileInfo
21542 CALL RemoveStr
21543 POP EDX
21544 PUSH EDX
21545 MOV EAX, EBX
21546 CALL System.@LStrCat
21548 @@3: CALL RemoveStr
21549 JMP @@loo
21551 @@fin: CALL RemoveStr
21552 POP ESI
21553 POP EBX
21554 end;
21555 {$ELSE ASM_VERSION} //Pascal
21556 function FileFullPath( const FileName: String ) : String;
21557 var SFI: TShFileInfo;
21558 Src, S: String;
21559 begin
21560 Result := '';
21561 Src := FileName;
21562 while Src <> '' do
21563 begin
21564 S := Parse( Src, '\' );
21565 if Result <> '' then
21566 Result := Result + '\';
21567 if (Result = '') and (Length( S ) = 2) and (S[ 2 ] = ':') then
21568 Result := S
21569 else
21570 begin
21571 ShGetFileInfo( PChar( Result + S ), 0, SFI, Sizeof( SFI ),
21572 SHGFI_DISPLAYNAME );
21573 if SFI.szDisplayName[ 0 ] <> #0 then
21574 S := SFI.szDisplayName;
21575 Result := Result + S;
21576 end;
21577 end;
21578 if ExtractFileExt( Result ) = '' then
21579 // case when flag 'Hide extensions for registered file types' is set on
21580 // in the Explorer:
21581 Result := Result + ExtractFileExt( FileName );
21582 end;
21583 {$ENDIF ASM_VERSION}
21584 //[END FileFullPath]
21586 //[function FileShortPath]
21587 function FileShortPath( const FileName: String ): String;
21588 var Buf: array[ 0..MAX_PATH ] of Char;
21589 begin
21590 GetShortPathName( PChar( FileName ), Buf, Sizeof( Buf ) );
21591 Result := Buf;
21592 end;
21594 //[function FileIconSystemIdx]
21595 function FileIconSystemIdx( const Path: String ): Integer;
21596 var SFI: TShFileInfo;
21597 begin
21598 SFI.iIcon := 0; // Bartov
21599 ShGetFileInfo( PChar( Path ), 0, SFI, sizeof( SFI ),
21600 //-- Babenko Alexey: -----------------//
21601 // SHGFI_ICON or //
21602 //----------------------------------//
21603 SHGFI_SMALLICON or SHGFI_SYSICONINDEX );
21604 Result := SFI.iIcon;
21605 end;
21607 //[function FileIconSysIdxOffline]
21608 function FileIconSysIdxOffline( const Path: String ): Integer;
21609 var SFI: TShFileInfo;
21610 begin
21611 SFI.iIcon := 0; // Bartov
21612 ShGetFileInfo( PChar( Path ), FILE_ATTRIBUTE_NORMAL, SFI, sizeof( SFI ),
21613 //-- Babenko Alexey: -----------------//
21614 //SHGFI_ATTRIBUTES or SHGFI_ICON or //
21615 //----------------------------------//
21616 SHGFI_SMALLICON or SHGFI_SYSICONINDEX or SHGFI_USEFILEATTRIBUTES );
21617 Result := SFI.iIcon;
21618 end;
21620 //[procedure LogFileOutput]
21621 procedure LogFileOutput( const filepath, str: String );
21622 var F: HFile;
21623 begin
21624 F := FileCreate( filepath, ofOpenWrite or ofOpenAlways );
21625 if F = INVALID_HANDLE_VALUE then Exit;
21626 FileSeek( F, 0, spEnd );
21627 FileWrite( F, {$IFNDEF _D2} String {$ENDIF}
21628 ( str + #13#10 )[ 1 ], Length( str ) + 2 );
21629 FileClose( F );
21630 end;
21632 //[function StrSaveToFile]
21633 function StrSaveToFile( const Filename, Str: String ): Boolean;
21634 begin
21635 Result := Mem2File( PChar( Filename ), PChar( Str ), Length( Str ) )
21636 = Length( Str );
21637 end;
21639 //[function StrLoadFromFile]
21640 function StrLoadFromFile( const Filename: String ): String;
21641 var F: HFile;
21642 begin
21643 Result := '';
21644 F := FileCreate( Filename, ofOpenRead or ofOpenExisting or ofShareDenyWrite );
21645 if F = INVALID_HANDLE_VALUE then Exit;
21646 Result := File2Str( F );
21647 FileClose( F ); {??ee(zhog); Dark Knight}
21648 end;
21650 //[function Mem2File]
21651 function Mem2File( Filename: PChar; Mem: Pointer; Len: Integer ): Integer;
21652 var F: HFile;
21653 begin
21654 Result := 0;
21655 F := FileCreate( Filename, ofOpenWrite or ofOpenAlways );
21656 if F = INVALID_HANDLE_VALUE then Exit;
21657 Result := FileWrite( F, Mem^, Len );
21658 FileClose( F );
21659 end;
21661 //[function File2Mem]
21662 function File2Mem( Filename: PChar; Mem: Pointer; MaxLen: Integer ): Integer;
21663 var F: HFile;
21664 begin
21665 Result := 0;
21666 F := FileCreate( Filename, ofOpenRead or ofOpenExisting or ofShareDenyWrite );
21667 if F = INVALID_HANDLE_VALUE then Exit;
21668 Result := FileRead( F, Mem^, MaxLen );
21669 FileClose( F );
21670 end;
21672 //[FUNCTION DirectoryExists]
21673 {$IFDEF ASM_VERSION}
21674 function DirectoryExists( const Name: string): Boolean;
21676 //CALL System.@LStrToPChar // Name must not be ''
21677 PUSH EAX
21678 CALL GetFileAttributes
21679 INC EAX
21680 JZ @@exit
21681 DEC EAX
21682 {$IFDEF PARANOIA}
21683 DB $24, FILE_ATTRIBUTE_DIRECTORY
21684 {$ELSE}
21685 AND AL, FILE_ATTRIBUTE_DIRECTORY
21686 {$ENDIF}
21687 SETNZ AL
21688 @@exit:
21689 end;
21690 {$ELSE ASM_VERSION} //Pascal
21691 function DirectoryExists(const Name: string): Boolean;
21693 Code: Integer;
21694 begin
21695 Code := GetFileAttributes(PChar(Name));
21696 Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
21697 end;
21698 {$ENDIF ASM_VERSION}
21699 //[END DirectoryExists]
21701 //[function CheckDirectoryContent]
21702 function CheckDirectoryContent( const Name: String; SubDirsOnly: Boolean; const Mask: String ): Boolean;
21703 var FD: TWin32FindData;
21704 FH: THandle;
21705 begin
21706 if not DirectoryExists( Name ) then
21707 Result := TRUE
21708 else
21709 begin
21710 FH := Windows.FindFirstFile( PChar( IncludeTrailingPathDelimiter( Name )
21711 + Mask ), FD );
21712 if FH = INVALID_HANDLE_VALUE then
21713 Result := TRUE
21714 else
21715 begin
21716 Result := TRUE;
21717 repeat
21718 if not StrIn( FD.cFileName, ['.','..'] ) then
21719 begin
21720 if SubDirsOnly and LongBool(FD.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY)
21721 or not SubDirsOnly then
21722 begin
21723 Result := FALSE;
21724 break;
21725 end;
21726 end;
21727 until not Windows.FindNextFile( FH, FD );
21728 Windows.FindClose( FH );
21729 end;
21730 end;
21731 end;
21733 //[function DirectoryEmpty]
21734 function DirectoryEmpty(const Name: String): Boolean;
21735 begin
21736 Result := CheckDirectoryContent( Name, FALSE, '*.*' );
21737 end;
21740 //[function DirectorySize]
21741 function DirectorySize( const Path: String ): I64;
21742 var DirList: PDirList;
21743 I: Integer;
21744 begin
21745 Result := MakeInt64( 0, 0 );
21746 DirList := NewDirList( Path, '*.*', 0 );
21747 for I := 0 to DirList.Count-1 do
21748 begin
21749 if LongBool( DirList.Items[ I ].dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY ) then
21750 Result := Add64( Result, DirectorySize( DirList.Path + DirList.Names[ I ] ) )
21751 else
21752 Result := Add64( Result, MakeInt64( DirList.Items[ I ].nFileSizeLow,
21753 DirList.Items[ I ].nFileSizeHigh ) );
21754 end;
21755 DirList.Free;
21756 end;
21759 //[function DirectoryHasSubdirs]
21760 function DirectoryHasSubdirs( const Path: String ): Boolean;
21761 begin
21762 Result := not CheckDirectoryContent( Path, TRUE, '*.*' );
21763 end;
21765 //[function GetFileList]
21766 function GetFileList(const dir: string): PStrList;
21768 Srch: TWin32FindData;
21769 flag: Integer;
21770 succ: boolean;
21771 begin
21772 result := nil;
21773 flag := FindFirstFile(PChar(dir), Srch);
21774 //succ := flag <> 0; //---------------------------------------
21775 succ := flag <> Integer(INVALID_HANDLE_VALUE); // M.V.Chirikov
21776 while succ do begin
21777 if (not (Srch.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY > 0))then begin
21778 if Result = nil then begin
21779 Result := NewStrList;
21780 end;
21781 Result.Add(Srch.cFileName);
21782 end;
21783 succ := FindNextFile(Flag, Srch);
21784 end;
21785 FindClose(Flag);
21786 end;
21788 //[function ExcludeTrailingChar]
21789 function ExcludeTrailingChar( const S: String; C: Char ): String;
21790 begin
21791 Result := S;
21792 if Result <> '' then
21793 if Result[ Length( Result ) ] = C then
21794 Delete( Result, Length( Result ), 1 );
21795 end;
21797 //[function IncludeTrailingChar]
21798 function IncludeTrailingChar( const S: String; C: Char ): String;
21799 begin
21800 Result := S;
21801 if (Result = '') or (Result[ Length( Result ) ] <> C) then
21802 Result := Result + C;
21803 end;
21805 //---------------------------------------------------------
21806 // Following functions/procedures are created by Edward Aretino:
21807 // IncludeTrailingPathDelimiter, ExcludeTrailingPathDelimiter,
21808 // ForceDirectories, CreateDir, ChangeFileExt
21809 //---------------------------------------------------------
21810 //[function IncludeTrailingPathDelimiter]
21811 function IncludeTrailingPathDelimiter(const S: string): string;
21812 begin
21813 {if CopyTail(S, 1) <> '\' then
21814 Result := S + '\'
21815 else
21816 Result := S;}
21817 Result := IncludeTrailingChar( S, '\' );
21818 end;
21820 //[function ExcludeTrailingPathDelimiter]
21821 function ExcludeTrailingPathDelimiter(const S: string): string;
21822 begin
21823 {Result := S;
21824 if Length(Result) = 0 then Exit;
21826 if (CopyTail(Result, 1) = '\') then
21827 DeleteTail(Result, 1);}
21828 Result := ExcludeTrailingChar( S, '\' );
21829 end;
21831 //[function ForceDirectories]
21832 function ForceDirectories(Dir: string): Boolean;
21833 begin
21834 Result := Length(Dir) > 0; {Centronix}
21835 If not Result then Exit;
21836 Dir := ExcludeTrailingPathDelimiter(Dir);
21837 If (Length(Dir) < 3) or DirectoryExists(Dir) or
21838 (ExtractFilePath(Dir) = Dir) then Exit; // avoid 'xyz:\' problem.
21839 Result := ForceDirectories(ExtractFilePath(Dir)) and CreateDir(Dir);
21840 end;
21842 //[function CreateDir]
21843 function CreateDir(const Dir: string): Boolean;
21844 begin
21845 Result := Windows.CreateDirectory(PChar(Dir), nil);
21846 end;
21848 //[function ChangeFileExt]
21849 function ChangeFileExt(FileName: String; const Extension: string): string;
21851 FileExt: String;
21852 begin
21853 FileExt := ExtractFileExt(FileName);
21854 DeleteTail(FileName, Length(FileExt));
21855 Result := FileName+ Extension;
21856 end;
21858 {$IFDEF ASM_VERSION}
21859 {$IFNDEF _D2}
21860 {$DEFINE ASM_LStrFromPCharLen}
21861 {$ENDIF}
21862 {$ENDIF ASM_VERSION}
21864 {$IFDEF ASM_LStrFromPCharLen}
21865 {$DEFINE ASM_DIRDelimiters}
21866 {$ENDIF}
21868 {$IFDEF ASM_VERSION}
21869 {$DEFINE ASM_DIRDelimiters}
21870 {$ENDIF ASM_VERSION}
21872 {$IFDEF ASM_DIRDelimiters}
21873 const
21874 DirDelimiters: PChar = ':\';
21875 {$ENDIF}
21877 //[FUNCTION ExtractFileName]
21878 {$IFDEF ASM_VERSION}
21879 function ExtractFileName( const Path : String ) : String;
21881 PUSH EDX
21882 PUSH EAX
21883 MOV EDX, [DirDelimiters]
21884 CALL __DelimiterLast
21885 POP EDX
21886 CMP byte ptr [EAX], 0
21887 JZ @@1
21888 XCHG EDX, EAX
21889 INC EDX
21890 @@1: POP EAX
21891 CALL System.@LStrFromPChar
21892 end;
21893 {$ELSE ASM_VERSION} //Pascal
21894 function ExtractFileName( const Path : String ) : String;
21895 var P: PChar;
21896 begin
21897 P := __DelimiterLast( PChar( Path ), ':\' );
21898 if P^ = #0 then
21899 Result := Path
21900 else
21901 Result := P + 1;
21902 end;
21903 {$ENDIF ASM_VERSION}
21904 //[END ExtractFileName]
21906 //[FUNCTION ExtractFilePath]
21907 {$IFDEF ASM_LStrFromPCharLen} // LStrFromPCharLen - there are no in D2
21908 function ExtractFilePath( const Path : String ) : String;
21910 PUSH EDX
21911 MOV EDX, [DirDelimiters]
21912 CALL EAX2PChar
21913 PUSH EAX
21914 CALL __DelimiterLast
21915 XCHG EDX, EAX
21916 XOR ECX, ECX
21917 POP EAX
21918 CMP byte ptr [EDX], CL
21919 JZ @@ret_0
21920 SUB EDX, EAX
21921 INC EDX
21922 XCHG EDX, EAX
21923 XCHG ECX, EAX
21924 @@ret_0:
21925 POP EAX
21926 CALL System.@LStrFromPCharLen
21927 end;
21928 {$ELSE} //Pascal
21929 function ExtractFilePath( const Path : String ) : String;
21930 //var I : Integer;
21931 var P, P0: PChar;
21932 begin
21933 P0 := PChar( Path );
21934 P := __DelimiterLast( P0, ':\' );
21935 if P^ = #0 then
21936 Result := ''
21937 else
21938 Result := Copy( Path, 1, P - P0 + 1 );
21939 end;
21940 {$ENDIF}
21942 //[function ExtractFileNameWOext]
21943 function ExtractFileNameWOext( const Path : String ) : String;
21944 begin
21945 Result := ExtractFileName( Path );
21946 Result := Copy( Result, 1, Length( Result ) - Length( ExtractFileExt( Result ) ) );
21947 end;
21949 {$IFDEF ASM_VERSION}
21950 const
21951 ExtDelimeters: PChar = '.';
21953 //[function ExtractFileExt]
21954 function ExtractFileExt( const Path : String ) : String;
21956 PUSH EDX
21957 MOV EDX, [ExtDelimeters]
21958 CALL EAX2PChar
21959 CALL __DelimiterLast
21960 @@1: XCHG EDX, EAX
21961 POP EAX
21962 CALL System.@LStrFromPChar
21963 end;
21964 {$ELSE ASM_VERSION} //Pascal
21965 function ExtractFileExt( const Path : String ) : String;
21966 var P: PChar;
21967 begin
21968 P := __DelimiterLast( PChar( Path ), '.' );
21969 Result := P;
21970 end;
21971 {$ENDIF ASM_VERSION}
21972 //[END ExtractFilePath]
21974 //[function ReplaceFileExt]
21975 function ReplaceFileExt( const Path, NewExt: String ): String;
21976 begin
21977 Result := ExtractFilePath( Path ) +
21978 ExtractFileNameWOext( ExtractFileName( Path ) ) +
21979 NewExt;
21980 end;
21982 //[function ExtractShortPathName]
21983 function ExtractShortPathName( const Path: String ): String;
21985 Buffer: array[0..MAX_PATH - 1] of Char;
21986 begin
21987 SetString(Result, Buffer,
21988 GetShortPathName(PChar(Path), Buffer, SizeOf(Buffer)));
21989 end;
21991 //[function FilePathShortened]
21992 function FilePathShortened( const Path: String; MaxLen: Integer ): String;
21993 begin
21994 Result := FilePathShortenPixels( Path, 0, MaxLen );
21995 end;
21997 //[function PixelsLength]
21998 function PixelsLength( DC: HDC; const Text: String ): Integer;
21999 var Sz: TSize;
22000 begin
22001 if DC = 0 then
22002 Result := Length( Text )
22003 else
22004 begin
22005 Windows.GetTextExtentPoint32( DC, PChar( Text ), Length( Text ), Sz );
22006 Result := Sz.cx;
22007 end;
22008 end;
22010 //[function FilePathShortenPixels]
22011 function FilePathShortenPixels( const Path: String; DC: HDC; MaxPixels: Integer ): String;
22012 var L0, L1: Integer;
22013 Prev: String;
22014 begin
22015 Result := Path;
22016 L0 := PixelsLength( DC, Result );
22017 while L0 > MaxPixels do
22018 begin
22019 Prev := Result;
22020 L1 := pos( '\...\', Result );
22021 if L1 <= 0 then
22022 Result := ExcludeTrailingPathDelimiter( ExtractFilePath( Result ) )
22023 else
22024 Result := Copy( Result, 1, L1 - 1 );
22025 if Result <> '' then
22026 Result := IncludeTrailingPathDelimiter( ExtractFilePath( Result ) ) + '...\' + ExtractFileName( Path );
22027 if (Result = '') or (Result = Prev) then
22028 begin
22029 L1 := Length( ExtractFilePath( Result ) );
22030 while (PixelsLength( DC, Result ) > MaxPixels) and (L1 > 1) do
22031 begin
22032 Dec( L1 );
22033 Result := Copy( Result, 1, L1 ) + '...\' + ExtractFileName( Result );
22034 end;
22035 if PixelsLength( DC, Result ) > MaxPixels then
22036 begin
22037 L1 := MaxPixels + 1;
22038 while ((MaxPixels > 0) and (L1 > 1) or (MaxPixels = 0) and (L1 > 0)) and
22039 (PixelsLength( DC, Result ) > MaxPixels) do
22040 begin
22041 Dec( L1 );
22042 Result := Copy( ExtractFileName( Path ), 1, L1 ) + '...';
22043 end;
22044 end;
22045 break;
22046 end;
22047 L0 := PixelsLength( DC, Result );
22048 end;
22049 end;
22051 //[procedure CutFirstDirectory]
22052 procedure CutFirstDirectory(var S: String);
22054 Root: Boolean;
22055 P: Integer;
22056 begin
22057 if S = '\' then
22058 S := ''
22059 else
22060 begin
22061 if S[1] = '\' then
22062 begin
22063 Root := True;
22064 Delete(S, 1, 1);
22066 else
22067 Root := False;
22068 if S[1] = '.' then
22069 Delete(S, 1, 4);
22070 P := pos('\',S);
22071 if P <> 0 then
22072 begin
22073 Delete(S, 1, P);
22074 S := '...\' + S;
22076 else
22077 S := '';
22078 if Root then
22079 S := '\' + S;
22080 end;
22081 end;
22083 //[function MinimizeName]
22084 function MinimizeName( const Path: String; DC: HDC; MaxPixels: Integer ): String;
22086 Drive, Dir, Name: String;
22087 begin
22088 Result := Path;
22089 Dir := ExtractFilePath(Result);
22090 Name := ExtractFileName(Result);
22092 if (Length(Dir) >= 2) and (Dir[2] = ':') then
22093 begin
22094 Drive := Copy(Dir, 1, 2);
22095 Delete(Dir, 1, 2);
22097 else
22098 Drive := '';
22099 while ((Dir <> '') or (Drive <> '')) and (PixelsLength(DC, Result) > MaxPixels) do
22100 begin
22101 if Dir = '\...\' then
22102 begin
22103 Drive := '';
22104 Dir := '...\';
22106 else if Dir = '' then
22107 Drive := ''
22108 else
22109 CutFirstDirectory(Dir);
22110 Result := Drive + Dir + Name;
22111 end;
22112 end;
22114 //[FUNCTION FileSize]
22115 {$IFDEF ASM_VERSION}
22116 function FileSize( const Path : String ) : Integer;
22117 const size_TWin32FindData = sizeof( TWin32FindData );
22119 ADD ESP, - size_TWin32FindData
22120 PUSH ESP
22121 //CALL System.@LStrToPChar // Path must not be ''
22122 PUSH EAX
22123 CALL FindFirstFile
22124 INC EAX
22125 JZ @@exit
22126 DEC EAX
22127 PUSH EAX
22128 CALL FindClose
22130 MOV EAX, [ESP].TWin32FindData.nFileSizeLow
22131 @@exit:
22132 ADD ESP, size_TWin32FindData
22133 end;
22134 {$ELSE ASM_VERSION} //Pascal
22135 function FileSize( const Path : String ) : Integer;
22136 var FD : TWin32FindData;
22137 FH : THandle;
22138 begin
22139 FH := FindFirstFile( PChar( Path ), FD );
22140 Result := 0;
22141 if FH = INVALID_HANDLE_VALUE then exit;
22142 Result := FD.nFileSizeLow;
22143 if ((FD.nFileSizeLow and $80000000) <> 0) or
22144 (FD.nFileSizeHigh <> 0) then Result := -1;
22145 FindClose( FH );
22146 end;
22147 {$ENDIF ASM_VERSION}
22148 //[END FileSize]
22151 //[function FileTimeCompare]
22152 function FileTimeCompare( const FT1, FT2 : TFileTime ) : Integer;
22153 var ST1, ST2 : TSystemTime;
22154 begin
22155 FileTimeToSystemTime( FT1, ST1 );
22156 FileTimeToSystemTime( FT2, ST2 );
22157 Result := CompareSystemTime( ST1, ST2 );
22158 end;
22160 //[function GetSystemDir]
22161 function GetSystemDir: String;
22162 var Buf: array[ 0..MAX_PATH ] of Char;
22163 begin
22164 GetSystemDirectory( @ Buf[ 0 ], MAX_PATH + 1 );
22165 Result := IncludeTrailingPathDelimiter( PChar( @ Buf[ 0 ] ) );
22166 end;
22169 //[function GetWindowsDir]
22170 function GetWindowsDir : string;
22171 var Buf : array[ 0..MAX_PATH ] of Char;
22172 begin
22173 GetWindowsDirectory( @Buf[ 0 ], MAX_PATH + 1 );
22174 Result := IncludeTrailingPathDelimiter( PChar( @ Buf[ 0 ] ) );
22175 end;
22177 //[function GetWorkDir]
22178 function GetWorkDir : string;
22179 var Buf: array[ 0..MAX_PATH ] of Char;
22180 begin
22181 GetCurrentDirectory( MAX_PATH + 1, @ Buf[ 0 ] );
22182 Result := IncludeTrailingPathDelimiter( PChar( @ Buf[ 0 ] ) );
22183 end;
22186 //[function GetTempDir]
22187 function GetTempDir : string;
22188 var Buf : array[ 0..MAX_PATH ] of Char;
22189 begin
22190 Windows.GetTempPath( MAX_PATH + 1, @Buf[ 0 ] );
22191 Result := IncludeTrailingPathDelimiter( PChar( @ Buf[ 0 ] ) );
22192 end;
22194 //[function CreateTempFile]
22195 function CreateTempFile( const DirPath, Prefix: String ): String;
22196 var Buf: array[ 0..MAX_PATH ] of Char;
22197 begin
22198 GetTempFileName( PChar( DirPath ), PChar( Prefix ), 0, Buf );
22199 Result := Buf;
22200 end;
22202 //[function GetFileListStr]
22203 function GetFileListStr(FPath{e.g.'c:\tmp\'}, FMask{e.g.'*.*'}: string): string;
22204 {* List of files in string, separating each path from others with semicolon (';').
22205 E.g.: 'c:\tmp\unit1.dcu;c:\tmp\unit1.~pa' (for use with DeleteFile2Recycle())}
22207 Srch: TWin32FindData;
22208 flag: Integer;
22209 succ: boolean;
22210 dir:string;
22211 begin
22212 result := '';
22213 if (FPath<>'') and (FPath[length(FPath)]<>'\') then FPath:=FPath+'\';
22214 if (FMask<>'') and (FMask[1]='\') then FMask:=CopyEnd(FMask,2);
22215 dir:=FPath+FMask;
22216 flag := FindFirstFile(PChar(dir), Srch);
22217 succ := flag <> 0;
22218 while succ do begin
22219 if (not (Srch.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY > 0))then begin
22220 if Result<>''then Result:=Result+';';
22221 Result:=Result+FPath+Srch.cFileName;
22222 end;
22223 succ := FindNextFile(Flag, Srch);
22224 end;
22225 FindClose(Flag);
22226 end;
22228 //[function DeleteFiles]
22229 function DeleteFiles( const DirPath: String ): Boolean;
22230 var Files, Name: String;
22231 begin
22232 Files := GetFileListStr( ExtractFilePath( DirPath ), ExtractFileName( DirPath ) );
22233 Result := TRUE;
22234 while Files <> '' do
22235 begin
22236 Name := Parse( Files, ';' );
22237 Result := Result and DeleteFile( PChar( Name ) );
22238 end;
22239 end;
22242 //[function DeleteFile2Recycle]
22243 function DeleteFile2Recycle( const Filename : String ) : Boolean;
22244 var FOS : TSHFileOpStruct;
22245 Buf : PChar;
22246 L : Integer;
22247 begin
22248 L := Length( Filename );
22249 GetMem( Buf, L + 2 );
22250 StrCopy( Buf, PChar( Filename ) );
22251 Buf[ L + 1 ] := #0;
22252 for L := L downto 0 do
22253 if Buf[ L ] = ';' then Buf[ L ] := #0;
22254 FillChar( FOS, Sizeof( FOS ), 0 );
22255 if Applet <> nil then
22256 FOS.Wnd := Applet.Handle;
22257 FOS.wFunc := FO_DELETE;
22258 FOS.pFrom := Buf;
22259 FOS.fFlags := FOF_ALLOWUNDO or FOF_NOCONFIRMATION;
22260 FOS.fAnyOperationsAborted := True;
22261 FOS.lpszProgressTitle := PChar( 'Delete ' + Filename + ' to Recycle bin' );
22262 Result := SHFileOperation( FOS ) = 0;
22263 if Result then
22264 Result := not FOS.fAnyOperationsAborted;
22265 FreeMem( Buf );
22266 end;
22268 //[function CopyMoveFiles]
22269 function CopyMoveFiles( const FromList, ToList: String; Move: Boolean ): Boolean;
22270 var FOS : TSHFileOpStruct;
22271 Buf : PChar;
22272 L : Integer;
22273 begin
22274 L := Length( FromList );
22275 GetMem( Buf, L + 2 );
22276 StrCopy( Buf, PChar( FromList ) );
22277 Buf[ L + 1 ] := #0;
22278 for L := L downto 0 do
22279 if Buf[ L ] = ';' then Buf[ L ] := #0;
22280 FillChar( FOS, Sizeof( FOS ), 0 );
22281 if Applet <> nil then
22282 FOS.Wnd := Applet.Handle;
22283 if Move then
22284 begin
22285 FOS.wFunc := FO_MOVE;
22286 FOS.lpszProgressTitle := PChar( 'Move files' );
22288 else
22289 begin
22290 FOS.wFunc := FO_COPY;
22291 FOS.lpszProgressTitle := PChar( 'Copy files' );
22292 end;
22293 FOS.pFrom := Buf;
22294 FOS.pTo := PChar( ToList + #0 );
22295 FOS.fFlags := FOF_ALLOWUNDO;
22296 FOS.fAnyOperationsAborted := True;
22297 Result := SHFileOperation( FOS ) = 0;
22298 if Result then
22299 Result := not FOS.fAnyOperationsAborted;
22300 FreeMem( Buf );
22301 end;
22304 //[function DiskFreeSpace]
22305 function DiskFreeSpace( const Path: String ): I64;
22306 type TGetDFSEx = function( Path: PChar; CallerFreeBytes, TotalBytes, FreeBytes: Pointer )
22307 : Bool; stdcall;
22308 var GetDFSEx: TGetDFSEx;
22309 Kern32: THandle;
22310 V: TOSVersionInfo;
22311 Ex: Boolean;
22312 SpC, BpS, NFC, TNC: DWORD;
22313 FBA, TNB: I64;
22314 begin
22315 GetDFSEx := nil;
22316 V.dwOSVersionInfoSize := Sizeof( V );
22317 GetVersionEx( V );
22318 Ex := FALSE;
22319 if V.dwPlatformId = VER_PLATFORM_WIN32_NT then
22320 begin
22321 Ex := V.dwMajorVersion >= 4;
22323 else
22324 if V.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS then
22325 begin
22326 Ex := V.dwMajorVersion > 4;
22327 if not Ex then
22328 if V.dwMajorVersion = 4 then
22329 begin
22330 Ex := V.dwMinorVersion > 0;
22331 if not Ex then
22332 Ex := LoWord( V.dwBuildNumber ) >= $1111;
22333 end;
22334 end;
22335 if Ex then
22336 begin
22337 Kern32 := GetModuleHandle( 'kernel32.dll' );
22338 GetDFSEx := GetProcAddress( Kern32, 'GetDiskFreeSpaceExA' );
22339 end;
22340 if Assigned( GetDFSEx ) then
22341 GetDFSEx( PChar( Path ), @ FBA, @ TNB, @Result )
22342 else
22343 begin
22344 GetDiskFreeSpace( PChar( Path ), SpC, BpS, NFC, TNC );
22345 Result := Mul64i( MakeInt64( SpC * BpS, 0 ), NFC );
22346 end;
22347 end;
22351 //[function GetUniqueFilename]
22352 function GetUniqueFilename( PathName: string ) : String;
22353 var Path, Nam, Ext : String;
22354 I, J, K : Integer;
22355 begin
22356 Result := PathName;
22357 Path := ExtractFilePath( PathName );
22358 if not DirectoryExists( Path ) then Exit;
22359 Nam := ExtractFileNameWOext( PathName );
22360 if Nam = '' then
22361 begin
22362 if Path[ Length( Path ) ] = '\' then
22363 Path := Copy( Path, 1, Length( Path ) - 1 );
22364 PathName := Path;
22365 Result := Path;
22366 end;
22367 Nam := ExtractFileNameWOext( PathName );
22368 Ext := ExtractFileExt( PathName );
22369 I := Length( Nam );
22370 for J := I downto 1 do
22371 if not (Nam[ J ] in [ '0'..'9' ]) then
22372 begin
22373 I := J;
22374 break;
22375 end;
22376 K := Str2Int( CopyEnd( Nam, I + 1 ) );
22377 while FileExists( Result ) do
22378 begin
22379 Inc( K );
22380 Result := Path + Copy( Nam, 1, I ) + Int2Str( K ) + Ext;
22381 end;
22382 end;
22384 //[FUNCTION GetStartDir]
22385 {$IFDEF ASM_VERSION}
22386 function GetStartDir : String;
22388 PUSH EBX
22389 MOV EBX, EAX
22391 XOR EAX, EAX
22392 MOV AH, 2
22393 SUB ESP, EAX
22394 MOV EDX, ESP
22395 PUSH EAX
22396 PUSH EDX
22397 PUSH 0
22398 CALL GetModuleFileName
22400 LEA EDX, [ESP + EAX]
22401 @@1: DEC EDX
22402 CMP byte ptr [EDX], '\'
22403 JNZ @@1
22405 INC EDX
22406 MOV byte ptr [EDX], 0
22408 MOV EAX, EBX
22409 MOV EDX, ESP
22410 CALL System.@LStrFromPChar
22412 ADD ESP, 200h
22413 POP EBX
22414 end;
22415 {$ELSE ASM_VERSION} //Pascal
22416 function GetStartDir : String;
22417 var Buffer:array[0..260] of Char;
22418 I : Integer;
22419 begin
22420 I := GetModuleFileName( 0, Buffer, Sizeof( Buffer ) );
22421 for I := I downto 0 do
22422 if Buffer[ I ] = '\' then
22423 begin
22424 Buffer[ I + 1 ] := #0;
22425 break;
22426 end;
22427 Result := Buffer;
22428 end;
22429 {$ENDIF ASM_VERSION}
22430 //[END GetStartDir]
22432 //[END FILES]
22436 { TDirList }
22438 //[function NewDirList]
22439 function NewDirList( const DirPath, Filter: String; Attr: DWORD ): PDirList;
22440 begin
22442 New( Result, Create );
22443 {+}{++}(*Result := PDirList.Create;*){--}
22444 Result.ScanDirectory( DirPath, Filter, Attr );
22445 end;
22446 //[END NewDirList]
22448 //[function NewDirListEx]
22449 function NewDirListEx( const DirPath, Filters: String; Attr: DWORD ): PDirList;
22450 begin
22452 New( Result, Create );
22453 {+}{++}(*Result := PDirList.Create;*){--}
22454 Result.ScanDirectoryEx( DirPath, Filters, Attr );
22455 end;
22456 //[END NewDirListEx]
22458 {$IFDEF ASM_VERSION}
22459 //[procedure TDirList.Clear]
22460 procedure TDirList.Clear;
22462 XOR ECX, ECX
22463 XCHG ECX, [EAX].fList
22464 JECXZ @@exit
22465 XCHG EAX, ECX
22466 CALL TList.Release
22467 @@exit:
22468 end;
22469 {$ELSE ASM_VERSION} //Pascal
22470 procedure TDirList.Clear;
22471 begin
22472 if FList <> nil then
22473 FList.Release;
22474 FList := nil;
22475 end;
22476 {$ENDIF ASM_VERSION}
22478 {$IFDEF ASM_VERSION}
22479 //[destructor TDirList.Destroy]
22480 destructor TDirList.Destroy;
22482 PUSH EBX
22483 MOV EBX, EAX
22484 CALL Clear
22485 LEA EAX, [EBX].FPath
22486 CALL System.@LStrClr
22487 XCHG EAX, EBX
22488 CALL TObj.Destroy
22489 POP EBX
22490 end;
22491 {$ELSE ASM_VERSION} //Pascal
22492 destructor TDirList.Destroy;
22493 begin
22494 Clear;
22495 FPath := '';
22496 inherited;
22497 end;
22498 {$ENDIF ASM_VERSION}
22500 //[FUNCTION FindFilter]
22501 {$IFDEF ASM_VERSION}
22502 function FindFilter( const Filter: String): String;
22504 XCHG EAX, EDX
22505 PUSH EAX
22506 CALL System.@LStrAsg
22507 POP EAX
22508 CMP dword ptr [EAX], 0
22509 JNE @@exit
22510 LEA EDX, @@mask_all
22511 JE System.@LStrFromPChar
22512 @@mask_all: DB '*.*',0
22513 @@exit:
22514 end;
22515 {$ELSE ASM_VERSION} //Pascal
22516 function FindFilter(const Filter: String): String;
22517 begin
22518 Result := Filter;
22519 if Result = '' then Result := '*.*';
22520 end;
22521 {$ENDIF ASM_VERSION}
22522 //[END FindFilter]
22525 //[function TDirList.Get]
22526 function TDirList.Get(Idx: Integer): PWin32FindData;
22527 begin
22528 Result := FList.fItems[ Idx ];
22529 end;
22531 {$IFDEF ASM_VERSION}
22532 //[function TDirList.GetCount]
22533 function TDirList.GetCount: Integer;
22535 MOV EAX, [EAX].fList
22536 TEST EAX, EAX
22537 {$IFDEF USE_CMOV}
22538 CMOVNZ EAX, [EAX].TList.fCount
22539 {$ELSE}
22540 JZ @@exit
22541 MOV EAX, [EAX].TList.fCount
22542 @@exit: {$ENDIF}
22543 end;
22544 {$ELSE ASM_VERSION} //Pascal
22545 function TDirList.GetCount: Integer;
22546 begin
22547 Result := 0;
22548 if FList = nil then Exit;
22549 Result := FList.Count;
22550 end;
22551 {$ENDIF ASM_VERSION}
22553 {$IFDEF ASM_VERSION}
22554 //[function TDirList.GetNames]
22555 function TDirList.GetNames(Idx: Integer): string;
22557 MOV EAX, [EAX].fList
22558 MOV EAX, [EAX].TList.fItems
22559 MOV EDX, [EAX + EDX*4]
22560 //*/////////////////////////////////////////////////////
22561 // ADD EDX, TWin32FindData.cFileName
22562 //*/////////////////////////////////////////////////////
22563 ADD EDX, offset TWin32FindData.cFileName //
22564 //*/////////////////////////////////////////////////////
22565 MOV EAX, ECX
22566 CALL System.@LStrFromPChar
22567 end;
22568 {$ELSE ASM_VERSION} //Pascal
22569 function TDirList.GetNames(Idx: Integer): string;
22570 begin
22571 Result := PChar(@PWin32FindData(fList.fItems[ Idx ]).cFileName[0]);
22572 //Result := PChar(@Items[Idx].cFileName[0]);
22573 end;
22574 {$ENDIF ASM_VERSION}
22576 //[function TDirList.GetIsDirectory]
22577 function TDirList.GetIsDirectory(Idx: Integer): Boolean;
22578 begin
22579 Result := LongBool( Items[ Idx ].dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY );
22580 end;
22582 {$IFDEF ASM_noVERSION}
22583 //[function TDirList.SatisfyFilter]
22584 function TDirList.SatisfyFilter(FileName: PChar; FileAttr,
22585 FindAttr: DWord): Boolean;
22587 PUSH EBX
22588 PUSH ESI
22589 PUSH EDI
22590 XCHG EBX, EAX // EBX = @ Self
22591 MOV EAX, [FindAttr]
22592 MOV EDI, EDX // EDI = FileName
22593 MOV EDX, EAX
22594 AND EDX, ECX
22595 CMP EDX, EAX
22596 JE @@1
22598 TEST AL, FILE_ATTRIBUTE_NORMAL
22599 JZ @@ret_false
22600 @@1:
22601 CMP word ptr [EDI], '.'
22602 JE @@1_1
22603 CMP word ptr [EDI], '..'
22604 JNE @@1_1
22605 CMP byte ptr [EDI+2], 0
22606 JNE @@1_1
22607 @@1_0:
22608 MOV ECX, [FindAttr]
22609 TEST CL, FILE_ATTRIBUTE_NORMAL
22610 JZ @@1_1
22611 CMP ECX, FILE_ATTRIBUTE_NORMAL
22612 JE @@1_1
22613 TEST AL, FILE_ATTRIBUTE_DIRECTORY
22614 JZ @@1_1
22615 TEST CL, FILE_ATTRIBUTE_DIRECTORY
22616 JNZ @@ret_true
22618 @@1_1:
22619 MOV ECX, [EBX].fFilters
22620 JECXZ @@ret_false //?
22622 MOV ESI, [ECX].TStrList.fList
22623 MOV ESI, [ESI].TList.fItems
22624 MOV ECX, [ECX].TStrList.fCount
22625 JECXZ @@ret_false
22627 @@2:
22628 LODSD
22629 TEST EAX, EAX
22630 JZ @@nx_filter
22632 PUSHAD
22634 MOV EDX, [EAX]
22635 CMP DX, $002E
22636 JE @@F_d_dd
22637 AND EDX, $FFFFFF
22638 CMP EDX, $002E2E
22639 JE @@F_d_dd
22641 MOV EDX, [EDI]
22642 CMP DX, $002E
22643 JE @@4
22644 AND EDX, $FFFFFF
22645 CMP EDX, $002E2E
22646 JE @@4
22647 JMP @@chk_anti
22649 @@F_d_dd:
22650 MOV EDX, EDI
22651 PUSH EAX
22652 CALL StrComp
22653 TEST EAX, EAX
22654 POP EAX
22655 JZ @@popad_ret_true
22657 @@chk_anti:
22658 XCHG EDX, EAX // EDX = filter[ i ]
22659 MOV EAX, EDI // EAX = FileName
22660 CMP byte ptr [EDX], '^'
22661 JNE @@3
22663 INC EDX
22664 CALL _2StrSatisfy
22665 TEST AL, AL
22666 JZ @@4
22667 POPAD
22668 JMP @@ret_false
22670 @@3: CALL _2StrSatisfy
22671 TEST AL, AL
22672 JZ @@4
22673 @@popad_ret_true:
22674 POPAD
22675 @@ret_true:
22676 MOV AL, 1
22677 JMP @@exit
22679 @@4: POPAD
22680 @@nx_filter:
22681 LOOP @@2
22683 @@ret_false:
22684 XOR EAX, EAX
22685 @@exit:
22686 POP EDI
22687 POP ESI
22688 POP EBX
22689 end;
22690 {$ELSE ASM_VERSION} //Pascal
22691 function TDirList.SatisfyFilter(FileName: PChar; FileAttr,
22692 FindAttr: DWord): Boolean;
22693 {$IFDEF F_P}
22694 const Dot: String = '.';
22695 {$ENDIF F_P}
22696 var I: Integer;
22697 F: PChar;
22698 HasOnlyNegFilters: Boolean;
22699 begin
22700 Result := (((FileAttr and FindAttr) = FindAttr) or
22701 LongBool(FindAttr and FILE_ATTRIBUTE_NORMAL));
22702 if not Result then Exit;
22704 if (FileName <> {$IFDEF F_P}Dot{$ELSE}'.'{$ENDIF}) and
22705 (FileName <> '..') then
22706 if LongBool( FindAttr and FILE_ATTRIBUTE_NORMAL ) and
22707 (FindAttr <> FILE_ATTRIBUTE_NORMAL) then
22708 if LongBool( FindAttr and FILE_ATTRIBUTE_DIRECTORY ) and
22709 LongBool( FileAttr and FILE_ATTRIBUTE_DIRECTORY ) then Exit;
22711 HasOnlyNegFilters := TRUE;
22712 for I := 0 to fFilters.fCount - 1 do
22713 begin
22714 F := PChar(fFilters.fList.fItems[ I ]);
22715 if F = '' then continue;
22717 if (F = {$IFDEF F_P}Dot{$ELSE}'.'{$ENDIF}) or (F = '..') then
22718 begin
22719 if FileName = F then
22720 Exit;
22722 else
22723 if (Filename = {$IFDEF F_P}Dot{$ELSE}'.'{$ENDIF}) or (FileName = '..') then
22724 begin
22725 //Result := FALSE;
22726 continue;
22727 end;
22729 if F[ 0 ] = '^' then
22730 begin
22731 if StrSatisfy( FileName, PChar(@F[ 1 ]) ) then
22732 begin
22733 Result := False;
22734 Exit;
22735 end;
22737 else
22738 begin
22739 HasOnlyNegFilters := FALSE;
22740 if StrSatisfy( FileName, F ) then
22741 begin
22742 Result := True;
22743 Exit;
22744 end;
22745 end;
22746 end;
22748 Result := HasOnlyNegFilters and
22749 (FileName <> {$IFDEF F_P}Dot{$ELSE}'.'{$ENDIF}) and
22750 (FileName <> '..');
22752 end;
22753 {$ENDIF ASM_VERSION}
22755 {$IFDEF ASM_VERSION}
22756 //[procedure TDirList.ScanDirectory]
22757 procedure TDirList.ScanDirectory(const DirPath, Filter: String;
22758 Attr: DWord);
22759 const sz_win32finddata = sizeof(TWin32FindData);
22761 PUSH EBX
22762 PUSH EDI
22763 MOV EBX, EAX
22765 PUSHAD
22766 CALL Clear
22767 CALL NewList
22768 MOV [EBX].fList, EAX
22769 POPAD
22771 PUSHAD
22772 LEA EAX, [EBX].fPath
22773 CALL System.@LStrAsg
22774 POPAD
22776 MOV EAX, [EBX].fPath
22777 TEST EAX, EAX
22778 JE @@exit
22780 PUSHAD
22781 LEA EDX, [EBX].fPath
22782 MOV EAX, [EDX]
22783 CALL IncludeTrailingPathDelimiter
22785 MOV EAX, [EBX].fFilters
22786 TEST EAX, EAX
22787 JNZ @@1
22788 CALL NewStrList
22789 MOV [EBX].fFilters, EAX
22790 POPAD
22792 PUSHAD
22793 PUSH ECX
22794 XCHG EAX, ECX
22795 MOV EDX, offset[@@star_d_star]
22796 CALL StrComp
22797 TEST AL, AL
22798 POP EDX
22799 JNZ @@asg_Filter
22800 MOV EDX, offset[@@star]
22801 @@asg_Filter:
22802 MOV EAX, [EBX].fFilters
22803 CALL TStrList.Add
22804 JMP @@1
22806 @@star_d_star:
22807 DB '*.*', 0
22808 DD -1, 1
22809 @@star: DB '*', 0
22811 @@1:
22812 POPAD
22814 ADD ESP, -sz_win32finddata
22815 XOR EDX, EDX
22816 PUSH EDX
22817 PUSH EDX
22818 XCHG EAX, ECX
22819 MOV EDX, ESP
22820 CALL FindFilter
22822 LEA EAX, [ESP+4]
22823 MOV EDX, [EBX].fPath
22824 POP ECX
22825 PUSH ECX
22826 CALL System.@LStrCat3
22827 CALL RemoveStr
22829 POP EAX
22830 MOV EDX, ESP
22831 PUSH EAX
22832 PUSH EDX
22833 PUSH EAX
22834 CALL FindFirstFile
22835 MOV EDI, EAX
22836 INC EAX
22837 MOV EAX, ESP
22839 PUSHFD
22840 CALL System.@LStrClr
22841 POPFD
22842 POP ECX
22844 JZ @@fin
22846 @@loop:
22847 MOV ECX, [ESP].TWin32FindData.dwFileAttributes
22848 PUSH [Attr]
22849 LEA EDX, [ESP+4].TWin32FindData.cFileName
22850 MOV EAX, EBX
22851 CALL SatisfyFilter
22853 TEST AL, AL
22854 JZ @@next
22856 MOV ECX, [EBX].fOnItem.TMethod.Code
22857 JECXZ @@accept
22858 MOV EAX, [EBX].fOnItem.TMethod.Data
22859 MOV ECX, ESP
22860 PUSH 1
22861 MOV EDX, ESP
22862 PUSH EDX
22863 MOV EDX, EBX
22864 CALL dword ptr [EBX].fOnItem.TMethod.Code
22865 POP ECX
22866 JECXZ @@next
22867 LOOP @@fin
22869 @@accept:
22870 MOV EAX, sz_win32finddata
22871 PUSH EAX
22872 CALL System.@GetMem
22873 PUSH EAX
22874 XCHG EDX, EAX
22875 MOV EAX, [EBX].fList
22876 CALL TList.Add
22877 POP EDX
22878 POP ECX
22879 MOV EAX, ESP
22880 CALL System.Move
22882 @@next:
22883 PUSH ESP
22884 PUSH EDI
22885 CALL FindNextFile
22886 TEST EAX, EAX
22887 JNZ @@loop
22889 PUSH EDI
22890 CALL FindClose
22892 @@fin:
22893 ADD ESP, sz_win32finddata
22894 @@exit:
22895 XOR EAX, EAX
22896 XCHG EAX, [EBX].fFilters
22897 CALL TObj.Free
22898 POP EDI
22899 POP EBX
22900 end;
22901 {$ELSE ASM_VERSION} //Pascal
22902 procedure TDirList.ScanDirectory(const DirPath, Filter: String;
22903 Attr: DWord);
22904 var FindData : TWin32FindData;
22905 E : PWin32FindData;
22906 FindHandle : THandle;
22907 Action: TDirItemAction;
22908 begin
22909 Clear;
22910 FList := NewList;
22911 FPath := DirPath;
22912 if FPath = '' then Exit;
22913 FPath := IncludeTrailingPathDelimiter( FPath );
22914 if fFilters = nil then
22915 begin
22916 fFilters := NewStrList;
22917 if Filter = '*.*' then
22918 fFilters.Add( '*' )
22919 else
22920 fFilters.Add( Filter );
22921 end;
22922 FindHandle := FindFirstFile( PChar( FPath + FindFilter( Filter ) ),
22923 FindData );
22924 if FindHandle = INVALID_HANDLE_VALUE then Exit;
22925 while True do
22926 begin
22927 if SatisfyFilter( PChar(@FindData.cFileName[0]),
22928 FindData.dwFileAttributes, Attr ) then
22929 begin
22930 Action := diAccept;
22931 if Assigned( OnItem ) then
22932 OnItem( @Self, FindData, Action );
22933 CASE Action OF
22934 diSkip: ;
22935 diAccept:
22936 begin
22937 GetMem( E, Sizeof( FindData ) );
22938 E^ := FindData;
22939 FList.Add( E );
22940 end;
22941 diCancel: break;
22942 END;
22943 end;
22944 if not FindNextFile( FindHandle, FindData ) then break;
22945 end;
22946 FindClose( FindHandle );
22947 fFilters.Free;
22948 fFilters := nil;
22949 end;
22950 {$ENDIF ASM_VERSION}
22952 {$IFDEF ASM_VERSION}
22953 //[procedure TDirList.ScanDirectoryEx]
22954 procedure TDirList.ScanDirectoryEx(const DirPath, Filters: String;
22955 Attr: DWord);
22957 PUSH EBX
22958 MOV EBX, EAX
22960 PUSHAD
22961 CALL NewStrList
22962 MOV [EBX].fFilters, EAX
22963 POPAD
22965 PUSHAD
22966 PUSH 0
22967 MOV EAX, ESP
22968 MOV EDX, ECX
22969 CALL System.@LStrLAsg
22970 @@1: MOV ECX, [ESP]
22971 JECXZ @@2
22972 MOV EAX, ESP
22973 MOV EDX, offset[@@semicolon]
22974 PUSH 0
22975 MOV ECX, ESP
22976 CALL Parse
22977 MOV EAX, [ESP]
22978 MOV EDX, ESP
22979 CALL Trim
22980 POP EDX
22981 PUSH EDX
22982 TEST EDX, EDX
22983 JZ @@filt_added
22984 MOV EAX, [EBX].fFilters
22985 CALL TStrList.Add
22986 @@filt_added:
22987 CALL RemoveStr
22988 JMP @@1
22990 // ';' string literal
22991 DD -1, 1
22992 @@semicolon:
22993 DB ';',0
22995 @@2: POP ECX
22996 POPAD
22997 XOR ECX, ECX
22998 PUSH [Attr]
22999 CALL ScanDirectory
23000 {XOR EAX, EAX
23001 XCHG EAX, [EBX].fFilters
23002 CALL TObj.Free}
23003 POP EBX
23004 @@exit:
23005 end;
23006 {$ELSE ASM_VERSION} //Pascal
23007 procedure TDirList.ScanDirectoryEx(const DirPath, Filters: String;
23008 Attr: DWord);
23009 var F, FF: String;
23010 begin
23011 FF := Filters;
23012 fFilters := NewStrList;
23013 while FF <> '' do
23014 begin
23015 F := Trim( Parse( FF, ';' ) );
23016 if F <> '' then
23017 fFilters.Add( F );
23018 end;
23019 ScanDirectory( DirPath, '', Attr );
23020 end;
23021 {$ENDIF ASM_VERSION}
23023 type
23024 PSortDirData = ^TSortDirData;
23025 TSortDirData = packed Record
23026 FoldersFirst, CaseSensitive : Boolean;
23027 Rules : array[ 0..11 ] of TSortDirRules;
23028 Dir : PDirList;
23029 end;
23031 //[FUNCTION CompareDirItems]
23032 {$IFDEF ASM_noVERSION}
23033 function CompareDirItems( const Data : PSortDirData; const e1, e2 : DWORD ) : Integer;
23035 PUSH EBX
23036 PUSH ESI
23037 PUSH EDI
23038 XCHG EBX, EAX
23039 MOV EAX, [EBX].TSortDirData.Dir
23040 MOV EAX, [EAX].TDirList.fList
23041 MOV EAX, [EAX].TList.fItems
23042 MOV ESI, [EAX+EDX*4]
23043 MOV EDI, [EAX+ECX*4]
23044 MOV DL, byte ptr[ESI].TWin32FindData.dwFileAttributes
23045 MOV DH, byte ptr[EDI].TWin32FindData.dwFileAttributes
23046 AND DX, 2020h
23047 XOR EAX, EAX
23048 CMP DL, DH
23049 JE @@1
23050 CMP [EBX].TSortDirData.FoldersFirst, AL
23051 JE @@1
23052 OR AL, DL
23053 JNE @@exit_near
23054 DEC EAX
23055 //JMP @@exit
23056 @@exit_near:
23057 POP EDI
23058 POP ESI
23059 POP EBX
23062 @@sdrByDateChanged:
23063 LEA EAX, [ESI].TWin32FindData.ftLastWriteTime
23064 LEA EDX, [EDI].TWin32FindData.ftLastWriteTime
23065 JMP @@sdrByDate1
23067 @@sdrByDateAccessed:
23068 LEA EAX, [ESI].TWin32FindData.ftLastAccessTime
23069 LEA EDX, [EDI].TWin32FindData.ftLastAccessTime
23070 JMP @@sdrByDate1
23072 @@jmp_table:
23073 DD offset[@@exit1], offset[@@2], offset[@@2]
23074 DD offset[@@sdrByName], offset[@@sdrByExt]
23075 DD offset[@@sdrBySize], offset[@@sdrBySize]
23076 DD offset[@@sdrByDateCreate], offset[@@sdrByDateChanged]
23077 DD offset[@@sdrByDateAccessed]
23079 @@1:
23080 LEA EDX, [EBX].TSortDirData.Rules
23081 PUSH EDX
23082 @@2:
23083 POP EDX
23084 XOR EAX, EAX
23085 MOV AL, [EDX]
23086 INC EDX
23087 PUSH EDX
23089 JMP dword ptr [@@jmp_table+EAX*4]
23090 //////// ///////////////////
23092 @@sdrByDateCreate:
23093 LEA EAX, [ESI].TWin32FindData.ftCreationTime
23094 LEA EDX, [EDI].TWin32FindData.ftCreationTime
23095 @@sdrByDate1:
23096 PUSH EDX
23097 PUSH EAX
23098 CALL CompareFileTime
23099 TEST EAX, EAX
23100 JE @@2
23101 JMP @@exit1
23103 @@sdrBySize:
23104 MOV EAX, [ESI].TWin32FindData.nFileSizeHigh
23105 SUB EAX, [EDI].TWin32FindData.nFileSizeHigh
23106 JNE @@sdrBySize1
23107 MOV EAX, [ESI].TWin32FindData.nFileSizeLow
23108 SUB EAX, [EDI].TWin32FindData.nFileSizeLow
23109 @@to_2:
23110 JE @@2
23111 @@sdrBySize1:
23112 POP EDX
23113 DEC EDX
23114 CMP byte ptr[EDX], sdrBySizeDescending
23115 JNE @@sdrBySize2
23116 NEG EAX
23117 @@sdrBySize2:
23118 JNE @@exit
23119 //////// ///////////////////
23121 DD -1, 1
23122 @@point:DB '.',0
23124 @@sdrByExt:
23125 LEA EAX, [EDI].TWin32FindData.cFileName
23126 MOV EDX, offset[@@point]
23127 PUSH EDX
23128 CALL __DelimiterLast
23129 POP EDX
23130 PUSH EAX
23131 LEA EAX, [ESI].TWin32FindData.cFileName
23132 CALL __DelimiterLast
23133 POP EDX
23134 JMP @@sdrByName0
23136 @@sdrByName:
23137 LEA EAX, [ESI].TWin32FindData.cFileName
23138 LEA EDX, [EDI].TWin32FindData.cFileName
23139 @@sdrByName0:
23140 CMP [EBX].TSortDirData.CaseSensitive, 0
23141 JNE @@sdrByName1
23142 CALL _AnsiCompareStrNoCase
23143 JMP @@sdrByName2
23144 @@sdrByName1:
23145 CALL _AnsiCompareStr
23146 @@sdrByName2:
23147 TEST EAX, EAX
23148 JE @@to_2
23149 //JMP @@exit1
23151 @@exit1:
23152 POP EDX
23153 @@exit:
23154 POP EDI
23155 POP ESI
23156 POP EBX
23157 end;
23158 {$ELSE ASM_VERSION} //Pascal
23159 function CompareDirItems( const Data : PSortDirData; const e1, e2 : DWORD ) : Integer;
23160 var I : Integer;
23161 Item1, Item2 : PWin32FindData;
23162 S1, S2 : PChar;
23163 IsDir1, IsDir2 : Boolean;
23164 Date1, Date2 : PFileTime;
23165 begin
23166 Item1 := Data.Dir.fList.fItems[ e1 ];
23167 Item2 := Data.Dir.fList.fItems[ e2 ];
23168 Result := 0;
23169 IsDir1 := (Item1.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) <> 0;
23170 IsDir2 := (Item2.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) <> 0;
23171 if (IsDir1 <> IsDir2) and Data.FoldersFirst then
23172 begin
23173 if IsDir1 then Result := -1 else Result := 1;
23174 exit;
23175 end;
23176 for I := 0 to High(Data.Rules) do
23177 begin
23178 case Data.Rules[ I ] of
23179 sdrByName:
23180 begin
23181 S1 := Item1.cFileName;
23182 S2 := Item2.cFileName;
23183 if not Data.CaseSensitive then
23184 Result := _AnsiCompareStrNoCase( S1, S2 )
23185 else
23186 Result := _AnsiCompareStr( S1, S2 );
23187 end;
23188 sdrByExt:
23189 begin
23190 S1 := Item1.cFileName;
23191 S2 := Item2.cFileName;
23192 S1 := __DelimiterLast( S1, '.' );
23193 S2 := __DelimiterLast( S2, '.' );
23194 if not Data.CaseSensitive then
23195 Result := _AnsiCompareStrNoCase( S1, S2 )
23196 else
23197 Result := _AnsiCompareStr( S1, S2 );
23198 end;
23199 sdrBySize, sdrBySizeDescending:
23200 begin
23201 if Item1.nFileSizeHigh < Item2.nFileSizeHigh then
23202 Result := -1
23203 else
23204 if Item1.nFileSizeHigh > Item2.nFileSizeHigh then
23205 Result := 1
23206 else
23207 if Item1.nFileSizeLow < Item2.nFileSizeLow then
23208 Result := -1
23209 else
23210 if Item1.nFileSizeLow > Item2.nFileSizeLow then
23211 Result := 1;
23212 if Data.Rules[ I ] = sdrBySizeDescending then
23213 Result := -Result;
23214 end;
23215 sdrByDateCreate:
23216 begin
23217 Date1 := @Item1.ftCreationTime;
23218 Date2 := @Item2.ftCreationTime;
23219 Result := CompareFileTime( Date1^, Date2^ );
23220 end;
23221 sdrByDateChanged:
23222 begin
23223 Date1 := @Item1.ftLastWriteTime;
23224 Date2 := @Item2.ftLastWriteTime;
23225 Result := CompareFileTime( Date1^, Date2^ );
23226 end;
23227 sdrByDateAccessed:
23228 begin
23229 Date1 := @Item1.ftLastAccessTime;
23230 Date2 := @Item2.ftLastAccessTime;
23231 Result := CompareFileTime( Date1^, Date2^ );
23232 end;
23233 end; {case}
23234 if Result <> 0 then break;
23235 end;
23236 end;
23237 {$ENDIF ASM_VERSION}
23238 //[END CompareDirItems]
23240 //[PROCEDURE SwapDirItems]
23241 {$IFDEF ASM_VERSION}
23242 procedure SwapDirItems( const Data : PSortDirData; const e1, e2 : DWORD );
23244 MOV EAX, [EAX].TSortDirData.Dir
23245 MOV EAX, [EAX].TDirList.fList
23246 MOV EAX, [EAX].TList.fItems
23247 LEA EDX, [EAX+EDX*4]
23248 LEA ECX, [EAX+ECX*4]
23249 MOV EAX, [EDX]
23250 XCHG EAX, [ECX]
23251 MOV [EDX], EAX
23252 end;
23253 {$ELSE ASM_VERSION} //Pascal
23254 procedure SwapDirItems( const Data : PSortDirData; const e1, e2 : DWORD );
23255 var Tmp : Pointer;
23256 begin
23257 Tmp := Data.Dir.FList.fItems[ e1 ];
23258 Data.Dir.FList.fItems[ e1 ] := Data.Dir.FList.fItems[ e2 ];
23259 Data.Dir.FList.fItems[ e2 ] := Tmp;
23260 end;
23261 {$ENDIF ASM_VERSION}
23262 //[END SwapDirItems]
23265 TSortDirData = packed Record
23266 FoldersFirst, CaseSensitive : Boolean;
23267 Rules : array[ 0..11 ] of TSortDirRules;
23268 Dir : PDirList;
23269 end;
23271 {$IFDEF ASM_VERSION}
23272 procedure TDirList.Sort(Rules: array of TSortDirRules);
23273 const high_DefSortDirRules = High( DefSortDirRules );
23275 PUSH EBX
23276 PUSH ESI
23277 XOR EBX,EBX
23278 CMP [EAX].fList, EBX
23279 JE @@exit
23281 PUSH EAX // prepare Dir = @Self
23282 XOR EAX, EAX
23283 PUSH EAX
23284 PUSH EAX
23285 PUSH EAX
23286 MOV ESI, ESP
23287 INC ECX // ECX = High(Rules)
23288 JZ @@2
23289 @@1: MOV AH, [EDX] // AH = Rules[ I ]
23290 INC EDX
23291 CALL @@add_rule
23292 LOOP @@1
23293 @@2: LEA EDX, [DefSortDirRules]
23294 MOV CL, high_DefSortDirRules + 1
23295 @@21: MOV AH, [EDX]
23296 INC EDX
23297 CALL @@add_rule
23298 LOOP @@21
23300 PUSH BX // prepare FoldersFirst(BL), CaseSensitive(BH)
23301 MOV EBX, [ESP].TSortDirData.Dir
23302 MOV EAX, ESP
23303 PUSH offset[SwapDirItems]
23304 MOV ECX, offset[CompareDirItems]
23305 MOV EDX, [EBX].fList
23306 MOV EDX, [EDX].TList.fCount
23307 CALL SortData
23309 ADD ESP, 18
23310 JMP @@exit
23312 @@add_rule:
23313 PUSH ESI
23314 PUSH ECX
23315 MOV CL, 11
23316 @@a1: LODSB
23317 TEST AL, AL
23318 JZ @@a2
23319 CMP AL, AH
23320 JE @@a3
23321 LOOP @@a1
23322 @@a2: DEC ESI
23323 MOV [ESI], AH
23324 CMP AH, sdrFoldersFirst
23325 JNE @@a4
23326 INC BL
23327 @@a4: CMP AH, sdrCaseSensitive
23328 JNE @@a3
23329 INC BH
23330 @@a3: POP ECX
23331 POP ESI
23334 @@exit:
23335 POP ESI
23336 POP EBX
23337 end;
23338 {$ELSE ASM_VERSION} //Pascal
23339 procedure TDirList.Sort(Rules: array of TSortDirRules);
23340 var SortDirData : TSortDirData;
23341 I, J : Integer;
23343 function RulePresent( Rule : TSortDirRules ) : Boolean;
23344 var K : Integer;
23345 begin
23346 Result := True;
23347 for K := J - 1 downto 0 do
23348 if Rule = SortDirData.Rules[ K ] then exit;
23349 Result := False;
23350 end;
23352 procedure AddRule( Rule : TSortDirRules );
23353 begin
23354 if J > High( SortDirData.Rules ) then exit;
23355 if RulePresent( Rule ) then exit;
23356 SortDirData.Rules[ J ] := Rule;
23357 Inc( J );
23358 end;
23359 begin
23360 if fList = nil then Exit;
23361 J := 0;
23362 for I := 0 to High(Rules) do
23363 AddRule( Rules[ I ] );
23364 for I := 0 to High(DefSortDirRules) do
23365 AddRule( DefSortDirRules[ I ] );
23366 while J < High( SortDirData.Rules ) do
23367 begin
23368 SortDirData.Rules[ J ] := sdrNone;
23369 Inc( J );
23370 end;
23372 SortDirData.Dir := @Self;
23373 SortDirData.FoldersFirst := RulePresent( sdrFoldersFirst );
23374 SortDirData.CaseSensitive := RulePresent( sdrCaseSensitive );
23375 SortData( Pointer( @SortDirData ), fList.fCount, @CompareDirItems, @SwapDirItems );
23376 end;
23377 {$ENDIF ASM_VERSION}
23380 //[function TDirList.FileList]
23381 function TDirList.FileList(const Separator: String; Dirs,
23382 FullPaths: Boolean): String;
23383 var I: Integer;
23384 begin
23385 Result := '';
23386 for I := 0 to Count-1 do
23387 begin
23388 if not Dirs and IsDirectory[ I ] then Continue;
23389 if FullPaths then
23390 Result := Result + Path;
23391 Result := Result + Names[ I ] + Separator;
23392 end;
23393 end;
23399 ////////////////////////////////////////////////////////////////////////
23402 // R E G I S T R Y
23405 ////////////////////////////////////////////////////////////////////////
23409 {++}(*
23410 function RegSetValueEx; external advapi32 name 'RegSetValueExA';
23411 *){--}
23414 { -- registry -- }
23416 //[function RegKeyOpenRead]
23417 function RegKeyOpenRead( Key: HKey; const SubKey: String ): HKey;
23418 begin
23419 if RegOpenKeyEx( Key, PChar( SubKey ), 0, KEY_READ, Result ) <> ERROR_SUCCESS then
23420 Result := 0;
23421 end;
23423 //[function RegKeyOpenWrite]
23424 function RegKeyOpenWrite( Key: HKey; const SubKey: String ): HKey;
23425 begin
23426 if RegOpenKeyEx( Key, PChar( SubKey ), 0, KEY_READ or KEY_WRITE, Result ) <> ERROR_SUCCESS then
23427 Result := 0;
23428 end;
23430 //[function RegKeyOpenCreate]
23431 function RegKeyOpenCreate( Key: HKey; const SubKey: String ): HKey;
23432 var dwDisp: DWORD;
23433 begin
23434 if RegCreateKeyEx( Key, PChar( SubKey ), 0, nil, 0, KEY_ALL_ACCESS, nil, Result,
23435 @dwDisp ) <> ERROR_SUCCESS then
23436 Result := 0;
23437 end;
23439 //[function RegKeyGetDw]
23440 function RegKeyGetDw( Key: HKey; const ValueName: String ): DWORD;
23441 var dwType, dwSize: DWORD;
23442 begin
23443 dwSize := sizeof( DWORD );
23444 Result := 0;
23445 if (Key = 0) or
23446 (RegQueryValueEx( Key, PChar( ValueName ), nil, @dwType, PByte( @Result ), @dwSize ) <> ERROR_SUCCESS)
23447 or (dwType <> REG_DWORD) then Result := 0;
23448 end;
23450 //[function RegKeyGetStr]
23451 function RegKeyGetStr( Key: HKey; const ValueName: String ): String;
23452 var dwType, dwSize: DWORD;
23453 Buffer: PChar;
23455 function Query: Boolean;
23456 begin
23457 Result := RegQueryValueEx( Key, PChar( ValueName ), nil, @dwType,
23458 Pointer( Buffer ), @dwSize ) = ERROR_SUCCESS;
23459 end;
23460 begin
23461 Result := '';
23462 if Key = 0 then Exit;
23463 dwSize := 0;
23464 Buffer := nil;
23465 if not Query or (dwType <> REG_SZ) then Exit;
23466 GetMem( Buffer, dwSize );
23467 if Query then
23468 Result := Buffer;
23469 FreeMem( Buffer );
23470 end;
23472 //[function RegKeyGetStrEx]
23473 function RegKeyGetStrEx( Key: HKey; const ValueName: String ): String;
23474 var dwType, dwSize: DWORD;
23475 Buffer, Buffer2: PChar;
23476 Sz: Integer;
23477 function Query: Boolean;
23478 begin
23479 Result := RegQueryValueEx( Key, PChar( ValueName ), nil, @dwType,
23480 Pointer( Buffer ), @dwSize ) = ERROR_SUCCESS;
23481 end;
23482 begin
23483 Result := '';
23484 if Key = 0 then Exit;
23485 dwSize := 0;
23486 Buffer := nil;
23487 if not Query or ((dwType <> REG_SZ) and (dwtype <> REG_EXPAND_SZ)) then Exit;
23488 GetMem( Buffer, dwSize );
23489 if Query then
23490 begin
23491 if dwtype = REG_EXPAND_SZ then
23492 begin
23493 //------------------------------------------------------ by Dmitry Zharov
23494 // Sz := ExpandEnvironmentStrings(Buffer,nil,0); 18-Aug-2004
23495 // SetLength( Result, Sz );
23496 // ExpandEnvironmentStrings(Buffer, PChar(Result), Sz);
23497 //---------------------------------------------//
23498 Sz := ExpandEnvironmentStrings(Buffer,nil,0); // bug in size detection! sometimes we get an additional 2 bytes at the end...
23499 GetMem(Buffer2,Sz); //
23500 ExpandEnvironmentStrings(Buffer, Buffer2, Sz); //
23501 Result:=Buffer2; //
23502 FreeMem(Buffer2); //
23503 //---------------------------------------------//
23505 else
23506 Result := Buffer;
23507 end;
23508 FreeMem( Buffer );
23509 end;
23511 //[function RegKeySetDw]
23512 function RegKeySetDw( Key: HKey; const ValueName: String; Value: DWORD ): Boolean;
23513 begin
23514 Result := (Key <> 0) and (RegSetValueEx( Key, PChar( ValueName ), 0, REG_DWORD, @Value, sizeof( DWORD ) )
23515 = ERROR_SUCCESS);
23516 end;
23518 //[function RegKeySetStr]
23519 function RegKeySetStr( Key: HKey; const ValueName: String; const Value: String ): Boolean;
23520 begin
23521 Result := (Key <> 0) and (RegSetValueEx( Key, PChar( ValueName ), 0,
23522 REG_SZ, PChar(Value),
23523 Length( Value ) + 1 ) = ERROR_SUCCESS);
23524 end;
23526 //[function RegKeySetStrEx]
23527 function RegKeySetStrEx( Key: HKey; const ValueName: string; const Value: string;
23528 expand: boolean): Boolean;
23529 var dwType: DWORD;
23530 begin
23531 dwType := REG_SZ;
23532 if expand then
23533 dwType := REG_EXPAND_SZ;
23534 Result := (Key <> 0) and (RegSetValueEx(Key, PChar(ValueName), 0, dwType,
23535 PChar(Value), Length(Value) + 1) = ERROR_SUCCESS);
23536 end;
23538 //[procedure RegKeyClose]
23539 procedure RegKeyClose( Key: HKey );
23540 begin
23541 if Key <> 0 then
23542 RegCloseKey( Key );
23543 end;
23545 //[function RegKeyDelete]
23546 function RegKeyDelete( Key: HKey; const SubKey: String ): Boolean;
23547 begin
23548 Result := FALSE;
23549 if Key <> 0 then
23550 Result := RegDeleteKey( Key, PChar( SubKey ) ) = ERROR_SUCCESS;
23551 end;
23553 //[function RegKeyDeleteValue]
23554 function RegKeyDeleteValue( Key: HKey; const SubKey: String ): Boolean;
23555 begin
23556 Result := FALSE;
23557 if Key <> 0 then
23558 Result := RegDeleteValue( Key, PChar( SubKey ) ) = ERROR_SUCCESS;
23559 end;
23561 //[function RegKeyExists]
23562 function RegKeyExists( Key: HKey; const SubKey: String ): Boolean;
23563 var K: Integer;
23564 begin
23565 if Key = 0 then
23566 begin
23567 Result := FALSE;
23568 Exit;
23569 end;
23570 K := RegKeyOpenRead( Key, SubKey );
23571 Result := K <> 0;
23572 if K <> 0 then
23573 RegKeyClose( K );
23574 end;
23576 //[function RegKeyValExists]
23577 function RegKeyValExists( Key: HKey; const ValueName: String ): Boolean;
23578 var dwType, dwSize: DWORD;
23579 begin
23580 Result := (Key <> 0) and
23581 (RegQueryValueEx( Key, PChar( ValueName ), nil,
23582 @dwType, nil, @dwSize ) = ERROR_SUCCESS);
23583 end;
23585 //[function RegKeyValueSize]
23586 function RegKeyValueSize( Key: HKey; const ValueName: String ): Integer;
23587 begin
23588 Result := 0;
23589 if Key = 0 then Exit;
23590 RegQueryValueEx( Key, PChar( ValueName ), nil, nil, nil, @ DWORD( Result ) );
23591 end;
23593 //[function RegKeyGetBinary]
23594 function RegKeyGetBinary( Key: HKey; const ValueName: String; var Buffer; Count: Integer ): Integer;
23595 begin
23596 Result := 0;
23597 if Key = 0 then Exit;
23598 Result := Count;
23599 RegQueryValueEx( Key, PChar( ValueName ), nil, nil, @ Buffer, @ Result );
23600 end;
23602 //[function RegKeySetBinary]
23603 function RegKeySetBinary( Key: HKey; const ValueName: String; const Buffer; Count: Integer ): Boolean;
23604 begin
23605 Result := (Key <> 0) and (RegSetValueEx( Key, PChar( ValueName ), 0,
23606 REG_BINARY, @ Buffer, Count ) = ERROR_SUCCESS);
23607 end;
23609 //[function RegKeyGetDateTime]
23610 function RegKeyGetDateTime(Key: HKey; const ValueName: String): TDateTime;
23611 begin
23612 RegKeyGetBinary( Key, ValueName, Result, Sizeof( Result ) );
23613 end;
23615 //[function RegKeySetDateTime]
23616 function RegKeySetDateTime(Key: HKey; const ValueName: String; DateTime: TDateTime): Boolean;
23617 begin
23618 Result := RegKeySetBinary( Key, ValueName, DateTime, Sizeof( DateTime ) );
23619 end;
23621 //-----------------------------------------------
23622 // functions by Valerian Luft <luft@valerian.de>
23623 //-----------------------------------------------
23624 //[function RegKeyGetSubKeys]
23625 function RegKeyGetSubKeys( const Key: HKEY; List: PStrList) : Boolean;
23627 I, Size, NumSubKeys, MaxSubKeyLen : DWORD;
23628 KeyName: String;
23629 begin
23630 Result := False;
23631 List.Clear ;
23632 if RegQueryInfoKey(Key, nil, nil, nil, @NumSubKeys, @MaxSubKeyLen, nil, nil, nil, nil,
23633 nil, nil) = ERROR_SUCCESS then
23634 begin
23635 if NumSubKeys > 0 then begin
23636 for I := 0 to NumSubKeys-1 do
23637 begin
23638 Size := MaxSubKeyLen+1;
23639 SetLength(KeyName, Size);
23640 //FillChar(KeyName[1],Size,#0);
23641 RegEnumKeyEx(Key, I, @KeyName[1], Size, nil, nil, nil, nil);
23642 SetLength(KeyName, lstrlen(@KeyName[1]));
23643 List.Add(KeyName);
23644 end;
23645 end;
23646 Result:= True;
23647 end;
23648 end;
23651 //[function RegKeyGetValueNames]
23652 function RegKeyGetValueNames(const Key: HKEY; List: PStrList): Boolean;
23654 I, Size, NumSubKeys, NumValueNames, MaxValueNameLen: DWORD;
23655 ValueName: String;
23656 begin
23657 List.Clear ;
23658 Result:=False;
23659 if RegQueryInfoKey(Key, nil, nil, nil, @NumSubKeys, nil, nil, @NumValueNames,
23660 @MaxValueNameLen, nil, nil, nil) = ERROR_SUCCESS then
23661 begin
23662 if NumValueNames > 0 then
23663 for I := 0 to NumValueNames - 1 do begin
23664 Size := MaxValueNameLen + 1;
23665 SetLength(ValueName, Size);
23666 //FillChar(ValueName[1],Size,#0);
23667 RegEnumValue(Key, I, @ValueName[1], Size, nil, nil, nil, nil);
23668 SetLength(ValueName, lstrlen(@ValueName[1]));
23669 List.Add(ValueName);
23670 end;
23671 Result := True;
23672 end ;
23673 end;
23676 //[function RegKeyGetValueTyp]
23677 function RegKeyGetValueTyp (const Key:HKEY; const ValueName: String) : DWORD;
23678 begin
23679 Result:= Key ;
23680 if Key <> 0 then
23681 RegQueryValueEx (Key,@ValueName[1],NIL,@Result,NIL,NIL)
23682 end;
23696 { -- TDirChange -- }
23698 const FilterFlags: array[ TFileChangeFilters ] of Integer = (
23699 FILE_NOTIFY_CHANGE_FILE_NAME, FILE_NOTIFY_CHANGE_DIR_NAME,
23700 FILE_NOTIFY_CHANGE_ATTRIBUTES, FILE_NOTIFY_CHANGE_SIZE,
23701 FILE_NOTIFY_CHANGE_LAST_WRITE, $20 {FILE_NOTIFY_CHANGE_LAST_ACCESS},
23702 $40 {FILE_NOTIFY_CHANGE_CREATION}, FILE_NOTIFY_CHANGE_SECURITY );
23704 //[FUNCTION _NewDirChgNotifier]
23705 {$IFDEF ASM_VERSION}
23706 function _NewDirChgNotifier: PDirChange;
23707 begin
23708 New( Result, Create );
23709 end;
23710 //[function NewDirChangeNotifier]
23711 function NewDirChangeNotifier( const Path: String; Filter: TFileChangeFilter;
23712 WatchSubtree: Boolean; ChangeProc: TOnDirChange )
23713 : PDirChange;
23714 const Dflt_Flags = FILE_NOTIFY_CHANGE_FILE_NAME or FILE_NOTIFY_CHANGE_DIR_NAME or
23715 FILE_NOTIFY_CHANGE_ATTRIBUTES or FILE_NOTIFY_CHANGE_SIZE or
23716 FILE_NOTIFY_CHANGE_LAST_WRITE;
23718 PUSH EBX
23719 PUSH ECX // [EBP-8] = WatchSubtree
23720 PUSH EDX // [EBP-12] = Filter
23721 PUSH EAX // [EBP-16] = Path
23722 CALL _NewDirChgNotifier
23723 XCHG EBX, EAX
23724 LEA EAX, [EBX].TDirChange.FPath
23725 POP EDX
23726 CALL System.@LStrAsg
23727 MOV EAX, [ChangeProc].TMethod.Code
23728 MOV [EBX].TDirChange.FOnChange.TMethod.Code, EAX
23729 MOV EAX, [ChangeProc].TMethod.Data
23730 MOV [EBX].TDirChange.FOnChange.TMethod.Data, EAX
23731 POP ECX
23732 MOV EAX, Dflt_Flags
23733 MOVZX ECX, CL
23734 JECXZ @@flags_ready
23735 PUSH ECX
23736 MOV EAX, ESP
23737 MOV EDX, offset[FilterFlags]
23738 XOR ECX, ECX
23739 MOV CL, 7
23740 CALL MakeFlags
23741 POP ECX
23742 @@flags_ready: // EAX = Flags
23743 POP EDX
23744 MOVZX EDX, DL // EDX = WatchSubtree
23745 PUSH EAX
23746 PUSH EDX
23747 PUSH [EBX].TDirChange.FPath
23748 CALL FindFirstChangeNotification
23749 MOV [EBX].TDirChange.FHandle, EAX
23750 INC EAX
23751 JZ @@fault
23752 PUSH EBX
23753 PUSH offset[TDirChange.Execute]
23754 CALL NewThreadEx
23755 MOV [EBX].TDirChange.FMonitor, EAX
23756 JMP @@exit
23757 @@fault:
23758 XCHG EAX, EBX
23759 CALL TObj.Free
23760 @@exit:
23761 XCHG EAX, EBX
23762 POP EBX
23763 end;
23764 {$ELSE ASM_VERSION} //Pascal
23765 function NewDirChangeNotifier( const Path: String; Filter: TFileChangeFilter;
23766 WatchSubtree: Boolean; ChangeProc: TOnDirChange )
23767 : PDirChange;
23768 var Flags: DWORD;
23769 begin
23771 New( Result, Create );
23772 {+}{++}(*Result := PDirChange.Create;*){--}
23774 Result.FPath := Path;
23775 Result.FOnChange := ChangeProc;
23776 if Filter = [ ] then
23777 Flags := FILE_NOTIFY_CHANGE_FILE_NAME or FILE_NOTIFY_CHANGE_DIR_NAME or
23778 FILE_NOTIFY_CHANGE_ATTRIBUTES or FILE_NOTIFY_CHANGE_SIZE or
23779 FILE_NOTIFY_CHANGE_LAST_WRITE
23780 else
23781 Flags := MakeFlags( @Filter, FilterFlags );
23782 Result.FHandle := FindFirstChangeNotification(PChar(Result.FPath),
23783 Bool( Integer( WatchSubtree ) ), Flags);
23784 if Result.FHandle <> INVALID_HANDLE_VALUE then
23785 Result.FMonitor := NewThreadEx( Result.Execute )
23786 else //MsgOK( 'Can not monitor ' + Result.FPath + #13'Error ' + Int2Str( GetLastError ) );
23787 begin
23788 Result.Free;
23789 Result := nil;
23790 end;
23791 end;
23792 {$ENDIF ASM_VERSION}
23793 //[END _NewDirChgNotifier]
23795 { TDirChange }
23797 {$IFDEF ASM_VERSION}
23798 //[procedure TDirChange.Changed]
23799 procedure TDirChange.Changed;
23801 MOV ECX, [EAX].FPath
23802 XCHG EDX, EAX
23803 MOV EAX, [EDX].FOnChange.TMethod.Data
23804 CALL [EDX].FOnChange.TMethod.Code
23805 end;
23806 {$ELSE ASM_VERSION} //Pascal
23807 procedure TDirChange.Changed;
23808 begin
23809 FOnChange(@Self, FPath); // must be assigned always!!!
23810 end;
23811 {$ENDIF ASM_VERSION}
23813 {$IFDEF ASM_VERSION}
23814 //[destructor TDirChange.Destroy]
23815 destructor TDirChange.Destroy;
23817 PUSH EBX
23818 XCHG EBX, EAX
23819 MOV ECX, [EBX].FMonitor
23820 JECXZ @@no_monitor
23821 XCHG EAX, ECX
23822 CALL TObj.Free
23823 @@no_monitor:
23824 MOV ECX, [EBX].FHandle
23825 JECXZ @@exit
23826 PUSH ECX
23827 CALL FindCloseChangeNotification
23828 @@exit:
23829 LEA EAX, [EBX].FPath
23830 CALL System.@LStrClr
23831 XCHG EAX, EBX
23832 CALL TObj.Destroy
23833 POP EBX
23834 end;
23835 {$ELSE ASM_VERSION} //Pascal
23836 destructor TDirChange.Destroy;
23837 begin
23838 if FMonitor <> nil then
23839 FMonitor.Free;
23840 if FHandle > 0 then // FHandle <> INVALID_HANDLE_VALUE AND FHandle <> 0
23841 FindCloseChangeNotification(FHandle);
23842 FPath := '';
23843 inherited;
23844 end;
23845 {$ENDIF ASM_VERSION}
23847 {$IFDEF ASM_noVERSION}
23848 //[function TDirChange.Execute]
23849 function TDirChange.Execute(Sender: PThread): Integer;
23851 PUSH EBX
23852 PUSH ESI
23853 XCHG EBX, EAX
23854 MOV ESI, EDX
23855 @@loo:
23856 MOVZX ECX, [ESI].TThread.FTerminated
23857 INC ECX
23858 LOOP @@e_loop
23860 MOV ECX, [EBX].FHandle
23861 INC ECX
23862 JZ @@e_loop
23864 PUSH INFINITE
23865 PUSH ECX
23866 CALL WaitForSingleObject
23867 OR EAX, EAX
23868 JNZ @@loo
23870 PUSH [EBX].FHandle
23871 MOV EAX, [EBX].FMonitor
23872 PUSH EBX
23873 PUSH offset[TDirChange.Changed]
23874 CALL TThread.Synchronize
23875 CALL FindNextChangeNotification
23876 JMP @@loo
23877 @@e_loop:
23879 POP ESI
23880 POP EBX
23881 XOR EAX, EAX
23882 end;
23883 {$ELSE ASM_VERSION} //Pascal
23884 function TDirChange.Execute(Sender: PThread): Integer;
23885 begin
23886 while (not Sender.Terminated and (FHandle <> INVALID_HANDLE_VALUE)) do
23887 if (WaitForSingleObject(FHandle, INFINITE) = WAIT_OBJECT_0) then
23888 begin
23889 if AppletTerminated then break;
23890 Applet.GetWindowHandle;
23891 FMonitor.Synchronize( Changed );
23892 FindNextChangeNotification(FHandle);
23893 end;
23894 Result := 0;
23895 end;
23896 {$ENDIF ASM_VERSION}
23910 //////////////////////////////////////////////////////////////////////
23913 // D A T E A N D T I M E
23916 //////////////////////////////////////////////////////////////////////
23928 { -- date and time utilities -- }
23930 {* This part of the unit contains date-time routines. It is not a simple compilation
23931 of Delphi VCL date-time. E.g., TDateTime type is not based on 31-Dec-1899,
23932 but it is based on 31-Dec-0000 instead, allowing easy manipulating of dates
23933 at all Christian era, and all other historical era too. }
23935 //[procedure DivMod]
23936 procedure DivMod(Dividend: Integer; Divisor: Word;
23937 var Result, Remainder: Word);
23938 {$IFDEF F_P}
23939 begin
23940 Result := Dividend div Divisor;
23941 Remainder := Dividend mod Divisor;
23942 end;
23943 {$ELSE DELPHI}
23945 PUSH EBX
23946 MOV EBX,EDX
23947 MOV EDX,EAX
23948 SHR EDX,16
23949 DIV BX
23950 MOV EBX,Remainder
23951 MOV [ECX],AX
23952 MOV [EBX],DX
23953 POP EBX
23954 end;
23955 {$ENDIF}
23957 {++}(*
23958 //[API GetLocalTime, GetSystemTime]
23959 procedure GetLocalTime; external kernel32 name 'GetLocalTime';
23960 procedure GetSystemTime; external kernel32 name 'GetSystemTime';
23961 *){--}
23964 //[function Now]
23965 function Now : TDateTime;
23966 var SystemTime : TSystemTime;
23967 begin
23968 GetLocalTime( SystemTime );
23969 SystemTime2DateTime( SystemTime, Result );
23970 end;
23972 //[function Date]
23973 function Date: TDateTime;
23974 begin
23975 Result := Trunc( Now );
23976 end;
23978 //[procedure DecodeDateFully]
23979 procedure DecodeDateFully( DateTime: TDateTime; var Year, Month, Day, DayOfWeek: WORD );
23980 var ST: TSystemTime;
23981 begin
23982 DateTime2SystemTime( DateTime, ST );
23983 Year := ST.wYear;
23984 Month := ST.wMonth;
23985 Day := ST.wDay;
23986 DayOfWeek := ST.wDayOfWeek;
23987 end;
23989 //[procedure DecodeDate]
23990 procedure DecodeDate( DateTime: TDateTime; var Year, Month, Day: WORD );
23991 var Dummy: Word;
23992 begin
23993 DecodeDateFully( DateTime, Year, Month, Day, Dummy );
23994 end;
23996 //[function EncodeDate]
23997 function EncodeDate( Year, Month, Day: WORD; var DateTime: TDateTime ): Boolean;
23998 var ST: TSystemTime;
23999 begin
24000 FillChar( ST, Sizeof( ST ), 0 );
24001 ST.wYear := Year;
24002 ST.wMonth := Month;
24003 ST.wDay := Day;
24004 Result := SystemTime2DateTime( ST, DateTime );
24005 end;
24007 //[FUNCTION CompareSystemTime]
24008 {$IFDEF ASM_VERSION}
24009 function CompareSystemTime( const D1, D2 : TSystemTime) : Integer; assembler;
24011 PUSH ESI
24012 PUSH EBX
24013 MOV ESI, EAX
24014 XOR EAX, EAX
24015 XOR ECX, ECX
24016 MOV CL, 8 // 8 words: wYear, wMonth,..., wMilliseconds
24017 @@loo:
24018 LODSW
24019 MOV BX, [EDX]
24020 INC EDX
24021 INC EDX
24023 CMP CL, 6
24024 JE @@cont // skip compare DayOfWeek
24026 SUB AX, BX
24027 JNE @@calc
24029 @@cont:
24030 LOOP @@loo
24031 JMP @@exit
24033 @@calc:
24034 SBB EAX, EAX
24035 {$IFDEF PARANOIA}
24036 DB $0C, 1
24037 {$ELSE}
24038 OR AL, 1
24039 {$ENDIF}
24041 @@exit:
24042 POP EBX
24043 POP ESI
24044 end;
24045 {$ELSE ASM_VERSION} //Pascal
24046 function CompareSystemTime(const D1, D2 : TSystemTime) : Integer;
24047 var R: Integer;
24048 procedure CompareFields(const F1, F2 : Integer);
24049 begin
24050 if R <> 0 then Exit;
24051 if F1 = F2 then Exit;
24052 if F1 < F2 then
24053 R := -1
24054 else
24055 R := 1;
24056 end;
24057 begin
24058 R := 0;
24059 CompareFields( D1.wYear, D2.wYear );
24060 CompareFields( D1.wMonth, D2.wMonth );
24061 CompareFields( D1.wDay, D2.wDay );
24062 CompareFields( D1.wHour, D2.wHour );
24063 CompareFields( D1.wMinute, D2.wMinute );
24064 CompareFields( D1.wSecond, D2.wSecond );
24065 CompareFields( D1.wMilliseconds, D2.wMilliseconds );
24066 Result := R;
24067 end;
24068 {$ENDIF ASM_VERSION}
24069 //[END CompareSystemTime]
24072 //[procedure IncDays]
24073 procedure IncDays( var SystemTime : TSystemTime; DaysNum : Integer );
24074 var DateTime : TDateTime;
24075 begin
24076 SystemTime2DateTime( SystemTime, DateTime );
24077 DateTime := DateTime + DaysNum;
24078 DateTime2SystemTime( DateTime, SystemTime );
24079 end;
24082 //[procedure IncMonths]
24083 procedure IncMonths( var SystemTime : TSystemTime; MonthsNum : Integer );
24084 var M : Integer;
24085 DateTime : TDateTime;
24086 begin
24087 M := SystemTime.wMonth + MonthsNum - 1;
24088 Inc( SystemTime.wYear, M div 12 );
24089 SystemTime.wMonth := M mod 12 + 1;
24091 // Normalize wDayOfWeek field:
24092 SystemTime2DateTime( SystemTime, DateTime );
24093 DateTime2SystemTime( DateTime, SystemTime );
24094 end;
24097 //[function IsLeapYear]
24098 function IsLeapYear(Year: Word): Boolean;
24099 begin
24100 Result := (Year mod 4 = 0) and ((Year mod 100 <> 0) or (Year mod 400 = 0));
24101 end;
24104 //[function SystemTime2DateTime]
24105 function SystemTime2DateTime(const SystemTime : TSystemTime; var DateTime : TDateTime ) : Boolean;
24106 var I : Integer;
24107 Day : Integer;
24108 DayTable: PDayTable;
24109 begin
24110 Result := False;
24111 DateTime := 0.0;
24112 DayTable := @MonthDays[IsLeapYear(SystemTime.wYear)];
24113 with SystemTime do
24114 //-------- by Vadim Petrov ----------------------------------------------------------------
24115 //if (wYear >= 1) and (wYear <= 9999) and (wMonth >= 1) and (wMonth <= 12) and
24116 // (wDay >= 1) and (wDay <= DayTable^[wMonth]) and
24117 // (wHour < 24) and (wMinute < 60) and (wSecond < 60) and (wMilliSeconds < 1000) then
24118 //---------------------------------------------------------------------------------------//
24119 if {(wYear >= 0) !always true! and} (wYear <= 9999) and
24120 {(wMonth >= 0) !always true! and} (wMonth <= 12) and
24121 {(wDay >= 0) !always true! and} (wDay <= DayTable^[wMonth]) and //
24122 (wHour < 24) and (wMinute < 60) and (wSecond < 60) and (wMilliSeconds < 1000) then //
24123 //---------------------------------------------------------------------------------------//
24124 begin
24125 Day := wDay;
24126 for I := 1 to wMonth - 1 do
24127 Inc(Day, DayTable^[I]);
24128 I := wYear - 1;
24129 //--------------- by Vadim Petrov ------++
24130 if I<0 then i := 0; //
24131 //--------------------------------------++
24132 DateTime := I * 365 + I div 4 - I div 100 + I div 400 + Day
24133 + (wHour * 3600000 + wMinute * 60000 + wSecond * 1000 + wMilliSeconds) / MSecsPerDay;
24134 Result := True;
24135 end;
24136 end;
24139 //[function DayOfWeek]
24140 function DayOfWeek(Date: TDateTime): Integer;
24141 begin
24142 Result := (Trunc( Date ) + 6) mod 7 + 1;
24143 end;
24146 //[function DateTime2SystemTime]
24147 function DateTime2SystemTime(const DateTime : TDateTime; var SystemTime : TSystemTime ) : Boolean;
24148 const
24149 D1 = 365;
24150 D4 = D1 * 4 + 1;
24151 D100 = D4 * 25 - 1;
24152 D400 = D100 * 4 + 1;
24153 var Days : Integer;
24154 Y, M, D, I: Word;
24155 MSec : Integer;
24156 DayTable: PDayTable;
24157 MinCount, MSecCount: Word;
24158 begin
24159 Days := Trunc( DateTime );
24160 MSec := Round((DateTime - Days) * MSecsPerDay);
24161 Result := False;
24162 with SystemTime do
24163 if Days > 0 then
24164 begin
24165 Dec(Days);
24166 Y := 1;
24167 while Days >= D400 do
24168 begin
24169 Dec(Days, D400);
24170 Inc(Y, 400);
24171 end;
24172 DivMod(Days, D100, I, D);
24173 if I = 4 then
24174 begin
24175 Dec(I);
24176 Inc(D, D100);
24177 end;
24178 Inc(Y, I * 100);
24179 DivMod(D, D4, I, D);
24180 Inc(Y, I * 4);
24181 DivMod(D, D1, I, D);
24182 if I = 4 then
24183 begin
24184 Dec(I);
24185 Inc(D, D1);
24186 end;
24187 Inc(Y, I);
24188 DayTable := @MonthDays[IsLeapYear(Y)];
24189 M := 1;
24190 while True do
24191 begin
24192 I := DayTable^[M];
24193 if D < I then Break;
24194 Dec(D, I);
24195 Inc(M);
24196 end;
24197 wYear := Y;
24198 wMonth := M;
24199 wDay := D + 1;
24200 wDayOfWeek := DayOfWeek( DateTime );
24201 DivMod(MSec, 60000, MinCount, MSecCount);
24202 DivMod(MinCount, 60, wHour, wMinute);
24203 DivMod(MSecCount, 1000, wSecond, wMilliSeconds);
24204 Result := True;
24205 end;
24206 end;
24208 function DateTime_DiffSysLoc: TDateTime;
24209 var ST, LT: TSystemTime;
24210 FT, FT1: TFileTime;
24211 D1, D2: TDateTime;
24212 begin
24213 GetSystemTime( ST );
24214 SystemTimeToFileTime( ST, FT );
24215 FileTimeToLocalFileTime( FT, FT1 );
24216 FileTimeToSystemTime( FT1, LT );
24217 SystemTime2DateTime( ST, D1 );
24218 SystemTime2DateTime( LT, D2 );
24219 Result := D2 - D1;
24220 end;
24222 //[function DateTime_System2Local]
24223 function DateTime_System2Local( DTSys: TDateTime ): TDateTime;
24224 begin
24225 Result := DTSys + DateTime_DiffSysLoc;
24226 end;
24228 //[function DateTime_Local2System]
24229 function DateTime_Local2System( DTLoc: TDateTime ): TDateTime;
24230 begin
24231 Result := DTLoc - DateTime_DiffSysLoc;
24232 end;
24235 //[function CatholicEaster]
24236 function CatholicEaster( nYear: Integer ): TDateTime;
24238 nMoon, nEpact, nSunday, nGold, nCent, nCorx, nCorz: Integer;
24239 SystemTime : TSystemTime;
24240 begin
24241 FillChar( SystemTime, Sizeof( SystemTime ), 0 );
24242 with SystemTime do
24243 begin
24245 wYear := nYear;
24247 { The Golden Number of the year in the 19 year Metonic Cycle }
24248 nGold := ( ( wYear mod 19 ) + 1 );
24250 { Calculate the Century }
24251 nCent := ( ( wYear div 100 ) + 1 );
24253 { No. of Years in which leap year was dropped in order to keep in step
24254 with the sun }
24255 nCorx := ( ( 3 * nCent ) div 4 - 12 );
24257 { Special Correction to Syncronize Easter with the moon's orbit }
24258 nCorz := ( ( 8 * nCent + 5 ) div 25 - 5 );
24260 { Find Sunday }
24261 nSunday := ( ( 5 * wYear ) div 4 - nCorx - 10 );
24263 { Set Epact (specifies occurance of full moon }
24264 nEpact := ( ( 11 * nGold + 20 + nCorz - nCorx ) mod 30 );
24266 if ( nEpact < 0 ) then
24267 nEpact := nEpact + 30;
24269 if ( ( nEpact = 25 ) and ( nGold > 11 ) ) or ( nEpact = 24 ) then
24270 nEpact := nEpact + 1;
24272 { Find Full Moon }
24273 nMoon := 44 - nEpact;
24275 if ( nMoon < 21 ) then
24276 nMoon := nMoon + 30;
24278 { Advance to Sunday }
24279 nMoon := ( nMoon + 7 - ( ( nSunday + nMoon ) mod 7 ) );
24281 if ( nMoon > 31 ) then
24282 begin
24283 wMonth := 4;
24284 wDay := ( nMoon - 31 );
24286 else
24287 begin
24288 wMonth := 3;
24289 wDay := nMoon;
24290 end;
24291 end;
24292 SystemTime2DateTime( SystemTime, Result );
24293 end;
24296 //[function SystemDate2Str]
24297 function SystemDate2Str( const SystemTime : TSystemTime; const LocaleID : DWORD;
24298 const DfltDateFormat : TDateFormat; const DateFormat : PChar ) : String;
24299 var Buf : PChar;
24300 Sz : Integer;
24301 Flags : DWORD;
24302 begin
24303 Sz := 100;
24304 Buf := nil;
24305 Result := '';
24306 Flags := 0;
24307 if DateFormat = nil then
24308 if DfltDateFormat = dfShortDate then
24309 Flags := DATE_SHORTDATE
24310 else
24311 Flags := DATE_LONGDATE;
24312 while True do
24313 begin
24314 if Buf <> nil then
24315 FreeMem( Buf );
24316 GetMem( Buf, Sz );
24317 if Buf = nil then Exit;
24318 if GetDateFormat( LocaleID, Flags, @SystemTime, DateFormat, Buf, Sz )
24319 = 0 then
24320 begin
24321 if GetLastError = ERROR_INSUFFICIENT_BUFFER then
24322 Sz := Sz * 2
24323 else
24324 break;
24326 else
24327 begin
24328 Result := Buf;
24329 break;
24330 end;
24331 end;
24332 if Buf <> nil then
24333 FreeMem( Buf );
24334 end;
24337 //[function SystemTime2Str]
24338 function SystemTime2Str( const SystemTime : TSystemTime; const LocaleID : DWORD;
24339 const Flags : TTimeFormatFlags; const TimeFormat : PChar ) : String;
24340 var Buf : PChar;
24341 Sz : Integer;
24342 Flg : DWORD;
24343 begin
24344 Sz := 100;
24345 Buf := nil;
24346 Result := '';
24347 Flg := 0;
24348 if tffNoMinutes in Flags then
24349 Flg := TIME_NOMINUTESORSECONDS
24350 else
24351 if tffNoSeconds in Flags then
24352 Flg := TIME_NOSECONDS;
24353 if tffNoMarker in Flags then
24354 Flg := Flg or TIME_NOTIMEMARKER;
24355 if tffForce24 in Flags then
24356 Flg := Flg or TIME_FORCE24HOURFORMAT;
24357 while True do
24358 begin
24359 if Buf <> nil then
24360 FreeMem( Buf );
24361 GetMem( Buf, Sz );
24362 if Buf = nil then Exit;
24363 if GetTimeFormat( LocaleID, Flg, @SystemTime, TimeFormat, Buf, Sz )
24364 = 0 then
24365 begin
24366 if GetLastError = ERROR_INSUFFICIENT_BUFFER then
24367 Sz := Sz * 2
24368 else
24369 break;
24371 else
24372 begin
24373 Result := Buf;
24374 break;
24375 end;
24376 end;
24377 if Buf <> nil then
24378 FreeMem( Buf );
24379 end;
24381 //[function Date2StrFmt]
24382 function Date2StrFmt( const Fmt: String; D: TDateTime ): String;
24383 var ST: TSystemTime;
24384 lpFmt: PChar;
24385 begin
24386 DateTime2SystemTime( D, ST );
24387 lpFmt := nil;
24388 if Fmt <> '' then lpFmt := PChar( Fmt );
24389 Result := SystemDate2Str( ST, LOCALE_USER_DEFAULT, dfShortDate, lpFmt );
24390 end;
24392 //[function Time2StrFmt]
24393 function Time2StrFmt( const Fmt: String; D: TDateTime ): String;
24394 var ST: TSystemTime;
24395 lpFmt: PChar;
24396 begin
24397 if D < 1 then D := D + 1;
24398 DateTime2SystemTime( D, ST );
24399 lpFmt := nil;
24400 if Fmt <> '' then lpFmt := PChar( Fmt );
24401 Result := SystemTime2Str( ST, LOCALE_USER_DEFAULT, [], lpFmt );
24402 end;
24404 //[function DateTime2StrShort]
24405 function DateTime2StrShort( D: TDateTime ): String;
24406 var ST: TSystemTime;
24407 begin
24408 //--------- by Vadim Petrov --------++
24409 if D < 1 then D := D + 1; //
24410 //----------------------------------++
24411 DateTime2SystemTime( D, ST );
24412 Result := SystemDate2Str( ST, LOCALE_USER_DEFAULT {GetUserDefaultLCID}, dfShortDate, nil ) + ' ' +
24413 SystemTime2Str( ST, LOCALE_USER_DEFAULT {GetUserDefaultLCID}, [], nil );
24414 end;
24416 //[function Str2DateTimeFmt]
24417 function Str2DateTimeFmt( const sFmtStr, sS: String ): TDateTime;
24418 var h12, hAM: Boolean;
24419 FmtStr, S: PChar;
24421 function GetNum( var S: PChar; NChars: Integer ): Integer;
24422 begin
24423 Result := 0;
24424 while (S^ <> #0) and (NChars <> 0) do
24425 begin
24426 Dec( NChars );
24427 if S^ in ['0'..'9'] then
24428 begin
24429 Result := Result * 10 + Ord(S^) - Ord('0');
24430 Inc( S );
24432 else
24433 break;
24434 end;
24435 end;
24437 function GetYear( var S: PChar; NChars: Integer ): Integer;
24438 var STNow: TSystemTime;
24439 OldDate: Boolean;
24440 begin
24441 Result := GetNum( S, NChars );
24442 GetSystemTime( STNow );
24443 OldDate := Result < 50;
24444 Result := Result + STNow.wYear - STNow.wYear mod 100;
24445 if OldDate then Dec( Result, 100 );
24446 end;
24448 function GetMonth( const fmt: String; var S: PChar ): Integer;
24449 var SD: TSystemTime;
24450 M: Integer;
24451 C, MonthStr: String;
24452 begin
24453 GetSystemTime( SD );
24454 for M := 1 to 12 do
24455 begin
24456 SD.wMonth := M;
24457 C := SystemDate2Str( SD, LOCALE_USER_DEFAULT, dfLongDate, PChar( fmt + '/dd/yyyy/' ) );
24458 MonthStr := Parse( C, '/' );
24459 if AnsiCompareStrNoCase( MonthStr, Copy( S, 1, Length( MonthStr ) ) ) = 0 then
24460 begin
24461 Result := M;
24462 Inc( S, Length( MonthStr ) );
24463 Exit;
24464 end;
24465 end;
24466 Result := 1;
24467 end;
24469 procedure SkipDayOfWeek( const fmt: String; var S: PChar );
24470 var SD: TSystemTime;
24471 Dt: TDateTime;
24472 D: Integer;
24473 C, DayWeekStr: String;
24474 begin
24475 GetSystemTime( SD );
24476 SystemTime2DateTime( SD, Dt );
24477 Dt := Dt - SD.wDayOfWeek;
24478 for D := 0 to 6 do
24479 begin
24480 DateTime2SystemTime( Dt, SD );
24481 C := SystemDate2Str( SD, LOCALE_USER_DEFAULT, dfLongDate, PChar( fmt + '/MM/yyyy/' ) );
24482 DayWeekStr := Parse( C, '/' );
24483 if AnsiCompareStrNoCase( DayWeekStr, Copy( S, 1, Length( DayWeekStr ) ) ) = 0 then
24484 begin
24485 Inc( S, Length( DayWeekStr ) );
24486 Exit;
24487 end;
24488 Dt := Dt + 1.0;
24489 end;
24490 end;
24492 procedure GetTimeMark( const fmt: String; var S: PChar );
24493 var SD: TSystemTime;
24494 AM: Boolean;
24495 C, TimeMarkStr: String;
24496 begin
24497 GetSystemTime( SD );
24498 SD.wHour := 0;
24499 for AM := FALSE to TRUE do
24500 begin
24501 C := SystemDate2Str( SD, LOCALE_USER_DEFAULT, dfLongDate, PChar( fmt + '/HH/mm' ) );
24502 TimeMarkStr := Parse( C, '/' );
24503 if AnsiCompareStrNoCase( TimeMarkStr, Copy( S, 1, Length( TimeMarkStr ) ) ) = 0 then
24504 begin
24505 Inc( S, Length( TimeMarkStr ) );
24506 hAM := AM;
24507 Exit;
24508 end;
24509 SD.wHour := 13;
24510 end;
24511 Result := 1;
24512 end;
24514 function FmtIs1( S: PChar ): Boolean;
24515 begin
24516 if StrIsStartingFrom( FmtStr, S ) then
24517 begin
24518 Inc( FmtStr, StrLen( S ) );
24519 Result := TRUE;
24521 else
24522 Result := FALSE;
24523 end;
24525 function FmtIs( S1, S2: PChar ): Boolean;
24526 begin
24527 Result := FmtIs1( S1 ) or FmtIs1( S2 );
24528 end;
24530 var ST: TSystemTime;
24531 begin
24532 FmtStr := PChar( sFmtStr);
24533 S := PChar( sS );
24534 FillChar( ST, Sizeof( ST ), 0 );
24535 h12 := FALSE;
24536 hAM := FALSE;
24537 while (FmtStr^ <> #0) and (S^ <> #0) do
24538 begin
24539 if (FmtStr^ in ['a'..'z','A'..'Z']) and (S^ in ['0'..'9']) then
24540 begin
24541 if FmtIs1( 'yyyy' ) then ST.wYear := GetNum( S, 4 )
24542 else if FmtIs1( 'yy' ) then ST.wYear := GetYear( S, 2 )
24543 else if FmtIs1( 'y' ) then ST.wYear := GetYear( S, -1 )
24544 else if FmtIs( 'dd', 'd' ) then ST.wDay := GetNum( S, 2 )
24545 else if FmtIs( 'MM', 'M' ) then ST.wMonth := GetNum( S, 2 )
24546 else if FmtIs( 'HH', 'H' ) then ST.wHour := GetNum( S, 2 )
24547 else if FmtIs( 'hh', 'h' ) then begin ST.wHour := GetNum( S, 2 ); h12 := TRUE end
24548 else if FmtIs( 'mm', 'm' ) then ST.wMinute := GetNum( S, 2 )
24549 else if FmtIs( 'ss', 's' ) then ST.wSecond := GetNum( S, 2 )
24550 else break; // + ECM
24552 else
24553 if (FmtStr^ in [ 'M', 'd', 'g' ]) then
24554 begin
24555 if FmtIs1( 'MMMM' ) then ST.wMonth := GetMonth( 'MMMM', S )
24556 else if FmtIs1( 'MMM' ) then ST.wMonth := GetMonth( 'MMM', S )
24557 else if FmtIs1( 'dddd' ) then SkipDayOfWeek( 'dddd', S )
24558 else if FmtIs1( 'ddd' ) then SkipDayOfWeek( 'ddd', S )
24559 else if FmtIs1( 'tt' ) then GetTimeMark( 'tt', S )
24560 else if FmtIs1( 't' ) then GetTimeMark( 't', S )
24561 else break; // + ECM
24563 else
24564 begin
24565 if FmtStr^ = S^ then
24566 Inc( FmtStr );
24567 Inc( S );
24568 end;
24569 end;
24571 if h12 then
24572 if hAM then
24573 Inc( ST.wHour, 12 );
24575 SystemTime2DateTime( ST, Result );
24576 end;
24578 var FmtBuf: PChar;
24579 DateSeparator : Char = #0; // + ECM
24581 //[function Str2DateTimeShort]
24582 function Str2DateTimeShort( const S: String ): TDateTime;
24583 var FmtStr, FmtStr2: String;
24585 function EnumDateFmt( lpstrFmt: PChar ): Boolean; stdcall;
24586 begin
24587 GetMem( FmtBuf, StrLen( lpstrFmt ) + 1 );
24588 StrCopy( FmtBuf, lpstrFmt );
24589 Result := FALSE;
24590 end;
24592 begin
24593 FmtStr := 'dd.MM.yyyy';
24594 FmtBuf := nil;
24595 EnumDateFormats( @ EnumDateFmt, LOCALE_USER_DEFAULT, DATE_SHORTDATE );
24596 if FmtBuf <> nil then
24597 begin
24598 FmtStr := FmtBuf;
24599 FreeMem( FmtBuf );
24600 end;
24602 FmtStr2 := 'H:mm:ss';
24603 FmtBuf := nil;
24604 EnumTimeFormats( @ EnumDateFmt, LOCALE_USER_DEFAULT, 0 );
24605 if FmtBuf <> nil then
24606 begin
24607 FmtStr2 := FmtBuf;
24608 FreeMem( FmtBuf );
24609 end;
24611 Result := Str2DateTimeFmt( FmtStr + ' ' + FmtStr2, S );
24612 end;
24614 // + ECM
24615 //[function Str2DateTimeShortEx]
24616 function Str2DateTimeShortEx( const S: String ): TDateTime;
24617 var St: String;
24618 Buff: Array[0..1] of Char;
24619 begin
24620 if DateSeparator = #0 then
24621 begin
24622 if GetLocaleInfo(GetThreadLocale,LOCALE_SDATE,Buff,2) > 0 then
24623 DateSeparator := Buff[0];
24624 end;
24625 St := S;
24626 if Pos(DateSeparator,S) = 0 then
24627 St := '0.0.0 '+S;
24628 Result := Str2DateTimeShort(St);
24629 end;
24648 ///////////////////////////////////////////////////////////////////////
24651 // T H R E A D S
24654 ///////////////////////////////////////////////////////////////////////
24663 { -- Thread -- }
24665 //[function ThreadFunc]
24666 function ThreadFunc(Thread: PThread): integer; stdcall;
24667 begin
24668 Result := Thread.Execute;
24669 end;
24671 {$IFDEF USE_CONSTRUCTORS}
24672 //[function NewThread]
24673 function NewThread: PThread;
24674 begin
24675 new( Result, ThreadCreate );
24676 end;
24677 //[END NewThread]
24678 {$ELSE not_USE_CONSTRUCTORS}
24680 //[function NewThread]
24681 function NewThread: PThread;
24682 begin
24683 {$IFNDEF FPC105ORBELOW}
24684 IsMultiThread := True;
24685 {$ENDIF}
24687 New( Result, Create );
24689 {++}(*Result := PThread.Create;*){--}
24690 Result.FSuspended := True;
24691 Result.FHandle := CreateThread( nil, // no security
24692 0, // the same stack size
24693 @ThreadFunc, // thread entry point
24694 Result, // parameter to pass to ThreadFunc
24695 CREATE_SUSPENDED, // always SUSPENDED
24696 Result.FThreadID ); // receive thread ID
24697 end;
24698 //[END NewThread]
24699 {$ENDIF USE_CONSTRUCTORS}
24701 {$IFDEF USE_CONSTRUCTORS}
24702 //[function NewThreadEx]
24703 function NewThreadEx( const Proc: TOnThreadExecute ): PThread;
24704 begin
24705 new( Result, ThreadCreateEx( Proc ) );
24706 end;
24707 {$ELSE not_USE_CONSTRUCTORS}
24709 //[FUNCTION NewThreadEx]
24710 {$IFDEF ASM_VERSION}
24711 function NewThreadEx( const Proc: TOnThreadExecute ): PThread;
24713 CALL NewThread
24714 POP EBP
24715 POP ECX
24716 POP EDX
24717 MOV [EAX].TThread.fOnExecute.TMethod.Code, EDX
24718 POP EDX
24719 MOV [EAX].TThread.fOnExecute.TMethod.Data, EDX
24720 PUSH ECX
24721 PUSH EAX
24722 CALL TThread.Resume
24723 POP EAX
24725 end;
24726 {$ELSE ASM_VERSION} //Pascal
24727 function NewThreadEx( const Proc: TOnThreadExecute ): PThread;
24728 begin
24729 Result := NewThread;
24730 Result.OnExecute := {++}(*{$IFDEF F_P} @ {$ENDIF}*){--}Proc;
24731 Result.Resume;
24732 end;
24733 {$ENDIF ASM_VERSION}
24734 //[END NewThreadEx]
24736 {$ENDIF USE_CONSTRUCTORS}
24738 //[function NewThreadAutoFree]
24739 function NewThreadAutoFree( const Proc: TOnThreadExecute ): PThread;
24740 begin
24741 Result := NewThread;
24742 Result.OnExecute := {++}(*{$IFDEF F_P} @ {$ENDIF}*){--}Proc;
24743 Result.F_AutoFree := TRUE;
24744 if Assigned( Proc ) then
24745 Result.Resume;
24746 end;
24748 { TThread }
24750 {$IFDEF ASM_VERSION}
24751 //[destructor TThread.Destroy]
24752 destructor TThread.Destroy;
24754 PUSH EBX
24755 MOV EBX, EAX
24756 CMP [EAX].FTerminated, 0
24757 JNZ @@1
24758 CALL Terminate
24759 MOV EAX, EBX
24760 CALL WaitFor
24761 @@1: MOV ECX, [EBX].FHandle
24762 JECXZ @@2
24763 PUSH ECX
24764 CALL CloseHandle
24765 @@2: POP EAX
24766 XCHG EBX, EAX
24767 JMP TObj.Destroy
24768 end;
24769 {$ELSE ASM_VERSION} //Pascal
24770 destructor TThread.Destroy;
24771 begin
24772 if not FTerminated then
24773 begin
24774 Terminate;
24775 WaitFor;
24776 end;
24777 if (FHandle <> 0) then
24778 CloseHandle(FHandle);
24779 inherited;
24780 end;
24781 {$ENDIF ASM_VERSION}
24784 //[function TThread.Execute]
24785 function TThread.Execute: integer;
24786 begin
24787 Result := 0;
24788 if Assigned( FOnExecute ) then
24789 Result := FOnExecute( @Self );
24790 if F_AutoFree then
24791 begin
24792 FTerminated := TRUE; // fake thread object (to prevent terminating while freeing)
24793 Free;
24794 end;
24795 end;
24798 //[function TThread.GetPriorityCls]
24799 function TThread.GetPriorityCls: Integer;
24800 begin
24801 Result := GetPriorityClass(FHandle);
24802 end;
24805 //[function TThread.GetThrdPriority]
24806 function TThread.GetThrdPriority: Integer;
24807 begin
24808 Result := GetThreadPriority(FHandle);
24809 end;
24812 //[procedure TThread.Resume]
24813 procedure TThread.Resume;
24814 begin
24815 FSuspended := False;
24816 if (ResumeThread(FHandle) > 1) then
24817 FSuspended := True
24818 else
24819 if Assigned(FOnResume) then
24820 FOnResume(@Self);
24821 end;
24824 //[procedure TThread.SetPriorityCls]
24825 procedure TThread.SetPriorityCls(Value: Integer);
24826 begin
24827 {$IFDEF DEBUG}
24828 if not SetPriorityClass(GetCurrentProcess, Value) then
24829 begin
24830 ShowMessage( SysErrorMessage( GetLastError ) );
24831 end;
24832 {$ELSE}
24833 SetPriorityClass(GetCurrentProcess, Value);
24834 {$ENDIF}
24835 end;
24838 //[procedure TThread.SetThrdPriority]
24839 procedure TThread.SetThrdPriority(Value: Integer);
24840 begin
24841 SetThreadPriority(FHandle, Value);
24842 end;
24845 //[procedure TThread.Suspend]
24846 procedure TThread.Suspend;
24847 begin
24848 FSuspended := TRUE;
24849 if Assigned(FOnSuspend) then
24850 Synchronize( FOnSuspend );
24851 SuspendThread(FHandle);
24852 end;
24855 //[procedure CallSynchronized]
24856 procedure CallSynchronized( Sender: PObj; Param: Pointer );
24857 var Thread: PThread;
24858 begin
24859 Thread := PThread( Sender );
24860 if Param <> nil then
24861 Thread.FMethodEx( Thread, Param )
24862 else
24863 Thread.FMethod( );
24864 end;
24867 //[procedure TThread.Synchronize]
24868 procedure TThread.Synchronize(Method: TThreadMethod);
24869 begin
24870 Global_Synchronized := CallSynchronized;
24871 FMethod := Method;
24872 if Applet <> nil then
24873 SendMessage( Applet.fHandle, CM_EXECPROC, 0, Integer( @Self ) );
24874 end;
24876 //[procedure TThread.SynchronizeEx]
24877 procedure TThread.SynchronizeEx( Method: TThreadMethodEx; Param: Pointer );
24878 begin
24879 Assert( Param <> nil, 'Parameter must not be NIL' );
24880 Global_Synchronized := CallSynchronized;
24881 FMethodEx := Method;
24882 SendMessage( Applet.fHandle, CM_EXECPROC, Integer( Param ), Integer( @Self ) );
24883 end;
24886 //[procedure TThread.Terminate]
24887 procedure TThread.Terminate;
24888 begin
24889 TerminateThread(FHandle,0);
24890 FTerminated := True;
24891 end;
24894 //[function TThread.WaitFor]
24895 function TThread.WaitFor: Integer;
24896 begin
24897 RefInc;
24898 Result := -1;
24899 if FHandle = 0 then Exit;
24900 WaitForSingleObject(FHandle, INFINITE);
24901 GetExitCodeThread(FHandle, DWORD(Result));
24902 RefDec;
24903 end;
24907 { TStream }
24909 {* This part of the unit contains implementation of streams for KOL. Please note,
24910 that both stream types (file stream and memory stream) are incapsulated
24911 by a single object type TStream. To avoid including unnedeed code,
24912 use constructing functions NewReadFileStream and NewWriteFileStream
24913 to work with file streams, which do not require both types of operation. }
24915 {* To create new type of stream, define your own methods, and in your
24916 constructing function, pass it to _NewStream function (through
24917 TStreamMethods record). In a field Custom, You can store a reference to
24918 your own data of any type (but do not forget to define correct releasing
24919 of such data in your fClose procedure). }
24921 //[function TStream.GetPosition]
24922 function TStream.GetPosition: DWord;
24923 begin
24924 Result := Seek( 0, spCurrent );
24925 end;
24927 //[procedure TStream.SetPosition]
24928 procedure TStream.SetPosition(Value: DWord);
24929 begin
24930 Seek( Value, spBegin );
24931 end;
24933 {$IFDEF ASM_VERSION}
24934 //[function TStream.GetSize]
24935 function TStream.GetSize: DWord;
24937 CALL [EAX].fMethods.fGetSiz
24938 end;
24939 {$ELSE ASM_VERSION} //Pascal
24940 function TStream.GetSize: DWord;
24941 begin
24942 Result := fMethods.fGetSiz( @Self );
24943 end;
24944 {$ENDIF ASM_VERSION}
24946 {$IFDEF ASM_VERSION}
24947 //[procedure TStream.SetSize]
24948 procedure TStream.SetSize(NewSize: DWord);
24950 CALL [EAX].fMethods.fSetSiz
24951 end;
24952 {$ELSE ASM_VERSION} //Pascal
24953 procedure TStream.SetSize(NewSize: DWord);
24954 begin
24955 fMethods.fSetSiz( @Self, NewSize );
24956 end;
24957 {$ENDIF ASM_VERSION}
24959 //[function TStream.GetFileStreamHandle]
24960 function TStream.GetFileStreamHandle: THandle;
24961 begin
24962 Result := fData.fHandle;
24963 end;
24965 {$IFDEF ASM_VERSION}
24966 //[function TStream.Read]
24967 function TStream.Read(var Buffer; Count: DWord): DWord;
24969 CALL [EAX].fMethods.fRead
24970 end;
24971 {$ELSE ASM_VERSION} //Pascal
24972 function TStream.Read(var Buffer; Count: DWord): DWord;
24973 begin
24974 Result := fMethods.fRead( @Self, Buffer, Count );
24975 end;
24976 {$ENDIF ASM_VERSION}
24978 //[function TStream.GetCapacity]
24979 function TStream.GetCapacity: DWORD;
24980 begin
24981 Result := fData.fCapacity;
24982 end;
24984 //[procedure TStream.SetCapacity]
24985 procedure TStream.SetCapacity(const Value: DWORD);
24986 var OldSize: DWORD;
24987 begin
24988 if fData.fCapacity >= Value then Exit;
24989 OldSize := Size;
24990 Size := Value;
24991 Size := OldSize;
24992 end;
24994 //[function TStream.Busy]
24995 function TStream.Busy: Boolean;
24996 begin
24997 Result := Assigned( fData.fThread );
24998 end;
25000 //[function TStream.DoAsyncRead]
25001 function TStream.DoAsyncRead( Sender: PThread ): Integer;
25002 begin
25003 Read( Pointer( fParam1 )^, fParam2 );
25004 fData.fThread := nil;
25005 Result := 0;
25006 end;
25008 //[procedure TStream.ReadAsync]
25009 procedure TStream.ReadAsync(var Buffer; Count: DWord);
25010 begin
25011 if Busy then Wait;
25012 fData.fThread := NewThreadAutoFree( nil );
25013 fData.fThread.OnExecute := DoAsyncRead;
25014 fParam1 := DWORD( @ Buffer );
25015 fParam2 := Count;
25016 fData.fThread.Resume;
25017 end;
25019 //[function TStream.DoAsyncSeek]
25020 function TStream.DoAsyncSeek( Sender: PThread ): Integer;
25021 begin
25022 Seek( fParam1, TMoveMethod( fParam2 ) );
25023 fData.fThread := nil;
25024 Result := 0;
25025 end;
25027 //[procedure TStream.SeekAsync]
25028 procedure TStream.SeekAsync(MoveTo: Integer; MoveMethod: TMoveMethod);
25029 begin
25030 if Busy then Wait;
25031 fData.fThread := NewThreadAutoFree( nil );
25032 fData.fThread.OnExecute := DoAsyncSeek;
25033 fParam1 := MoveTo;
25034 fParam2 := Ord( MoveMethod );
25035 fData.fThread.Resume;
25036 end;
25038 //[function TStream.DoAsyncWrite]
25039 function TStream.DoAsyncWrite( Sender: PThread ): Integer;
25040 begin
25041 Write( Pointer( fParam1 )^, fParam2 );
25042 fData.fThread := nil;
25043 Result := 0;
25044 end;
25046 //[procedure TStream.WriteAsync]
25047 procedure TStream.WriteAsync(var Buffer; Count: DWord);
25048 begin
25049 if Busy then Wait;
25050 fData.fThread := NewThreadAutoFree( nil );
25051 fData.fThread.OnExecute := DoAsyncWrite;
25052 fParam1 := DWORD( @ Buffer );
25053 fParam2 := Count;
25054 fData.fThread.Resume;
25055 end;
25057 //[procedure TStream.Wait]
25058 procedure TStream.Wait;
25059 begin
25060 if not Assigned( fData.fThread ) then Exit;
25061 if Assigned( fMethods.fWait ) then
25062 fMethods.fWait( @Self )
25063 else
25064 fData.fThread.WaitFor;
25065 end;
25067 {$IFDEF ASM_VERSION}
25068 //[function TStream.Write]
25069 function TStream.Write(var Buffer; Count: DWord): DWord;
25071 CALL [EAX].fMethods.fWrite
25072 end;
25073 {$ELSE ASM_VERSION} //Pascal
25074 function TStream.Write(var Buffer; Count: DWord): DWord;
25075 begin
25076 Result := fMethods.fWrite( @Self, Buffer, Count );
25077 end;
25078 {$ENDIF ASM_VERSION}
25080 //[function TStream.WriteStr]
25081 function TStream.WriteStr(S: String): DWORD;
25082 begin
25083 if S <> '' then
25084 Result := fMethods.fWrite( @Self, S[1], Length( S ) )
25085 else
25086 Result := 0;
25087 end;
25089 //[function TStream.ReadStrZ]
25090 function TStream.ReadStrZ: String;
25091 var C: Char;
25092 begin
25093 Result := '';
25094 REPEAT
25095 C := #0;
25096 Read( C, 1 );
25097 if C <> #0 then Result := Result + C;
25098 UNTIL C = #0;
25099 end;
25101 //[function TStream.ReadStr]
25102 function TStream.ReadStr: String;
25103 var C: Char;
25104 begin
25105 Result := '';
25106 REPEAT
25107 C := #0;
25108 Read( C, 1 );
25109 if C <> #0 then
25110 begin
25111 if C = #13 then
25112 begin
25113 C := #0;
25114 Read( C, 1 );
25115 if C <> #10 then Position := Position - 1;
25116 C := #13;
25118 else
25119 if C = #10 then
25120 C := #13;
25121 if C <> #13 then
25122 Result := Result + C;
25123 end;
25124 UNTIL C in [ #13, #0 ];
25125 end;
25127 //[function TStream.WriteStrZ]
25128 function TStream.WriteStrZ(S: String): DWORD;
25129 var C: Char;
25130 begin
25131 if S = '' then
25132 begin
25133 C := #0;
25134 Result := Write( C, 1 );
25136 else
25137 Result := Write( S[ 1 ], Length( S ) + 1 );
25138 end;
25140 //[function TStream.WriteStrEx]
25141 function TStream.WriteStrEx(S: String): DWord;
25142 begin
25143 result:=length(s);
25144 fmethods.fwrite(@self,result,Sizeof(DWORD));
25145 if result<>0 then result:=fmethods.fwrite(@self,s[1],result);
25146 end;
25148 //[function TStream.ReadStrExVar]
25149 function TStream.ReadStrExVar(var S: String): DWord;
25150 begin
25151 fmethods.fread(@self,result,Sizeof(DWORD));
25152 setlength(s,result);
25153 if result<>0 then result:=fmethods.fread(@self,s[1],result);
25154 end;
25156 //[function TStream.ReadStrEx]
25157 function TStream.ReadStrEx: String;
25158 begin
25159 readstrexvar(result);
25160 end;
25162 //[function TStream.WriteStrPas]
25163 function TStream.WriteStrPas( S: String ): DWORD;
25164 var L: Integer;
25165 begin
25166 Result := 0;
25167 L := Length( S );
25168 if L > 255 then L := 255;
25169 if Write( L, 1 ) < 1 then Exit;
25170 Result := 1;
25171 if L > 0 then
25172 Result := Write( S[ 1 ], L ) + 1;
25173 end;
25175 //[function TStream.ReadStrPas]
25176 function TStream.ReadStrPas: String;
25177 var L: Byte;
25178 begin
25179 Result := '';
25180 if Read( L, 1 ) < 1 then Exit;
25181 SetLength( Result, L );
25182 L := Read( Result[ 1 ], L );
25183 Result := Copy( Result, 1, L );
25184 end;
25187 {$IFDEF ASM_VERSION}
25188 //[function TStream.Seek]
25189 function TStream.Seek(MoveTo: integer; MoveMethod: TMoveMethod): DWord;
25191 CALL [EAX].fMethods.fSeek
25192 end;
25193 {$ELSE ASM_VERSION} //Pascal
25194 function TStream.Seek(MoveTo: integer; MoveMethod: TMoveMethod): DWord;
25195 begin
25196 Result := fMethods.fSeek( @Self, MoveTo, MoveMethod );
25197 end;
25198 {$ENDIF ASM_VERSION}
25200 {$IFDEF ASM_VERSION}
25201 //[destructor TStream.Destroy]
25202 destructor TStream.Destroy;
25204 PUSH EAX
25205 PUSH [EAX].fData.fThread
25206 CALL [EAX].fMethods.fClose
25207 POP EAX
25208 CALL TObj.Free
25209 POP EAX
25210 CALL TObj.Destroy
25211 end;
25212 {$ELSE ASM_VERSION} //Pascal
25213 destructor TStream.Destroy;
25214 begin
25215 fMethods.fClose( @Self );
25216 fData.fThread.Free;
25217 inherited;
25218 end;
25219 {$ENDIF ASM_VERSION}
25221 //+-
25222 //[function _NewStream]
25223 function _NewStream( const StreamMethods: TStreamMethods ): PStream;
25224 begin
25226 New( Result, Create );
25227 {+}{++}(*Result := PStream.Create;*){--}
25228 Move( StreamMethods, Result.fMethods, Sizeof( TStreamMethods ) );
25229 Result.fPMethods := @Result.fMethods;
25230 end;
25233 //[function SeekFileStream]
25234 function SeekFileStream( Strm: PStream; MoveTo: Integer; MoveFrom: TMoveMethod ): DWORD;
25235 begin
25236 Result := FileSeek( Strm.fData.fHandle, MoveTo, MoveFrom );
25237 end;
25240 //[function GetSizeFileStream]
25241 function GetSizeFileStream( Strm: PStream ): DWORD;
25242 begin
25243 Result := GetFileSize( Strm.fData.fHandle, nil );
25244 if Result = DWORD( -1 ) then Result := 0;
25245 end;
25247 //[procedure DummySetSize]
25248 procedure DummySetSize( Strm: PStream; Value: DWORD );
25249 begin
25250 end;
25252 //[procedure DummyStreamProc]
25253 procedure DummyStreamProc(Strm: PStream);
25254 begin
25255 end;
25257 //[function DummyReadWrite]
25258 function DummyReadWrite( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
25260 XOR EAX, EAX
25261 end;
25263 //[function ReadFileStream]
25264 function ReadFileStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
25265 begin
25266 Result := FileRead( Strm.fData.fHandle, Buffer, Count );
25267 end;
25269 //[function WriteFileStream]
25270 function WriteFileStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
25271 begin
25272 Result := FileWrite( Strm.fData.fHandle, Buffer, Count );
25273 end;
25275 //[FUNCTION WriteFileStreamEOF]
25276 {$IFDEF ASM_VERSION}
25277 function WriteFileStreamEOF( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
25279 PUSH EBX
25280 PUSH [EAX].TStream.fData.fHandle
25281 CALL WriteFileStream
25282 XCHG EBX, EAX
25283 CALL SetEndOfFile
25284 XCHG EAX, EBX
25285 POP EBX
25286 end;
25287 {$ELSE ASM_VERSION} //Pascal
25288 function WriteFileStreamEOF( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
25289 begin
25290 Result := WriteFileStream( Strm, Buffer, Count );
25291 SetEndOfFile( Strm.fData.fHandle );
25292 end;
25293 {$ENDIF ASM_VERSION}
25294 //[END WriteFileStreamEOF]
25296 //[procedure CloseFileStream]
25297 procedure CloseFileStream( Strm: PStream );
25298 begin
25299 FileClose( Strm.fData.fHandle );
25300 end;
25302 //[FUNCTION SeekMemStream]
25303 {$IFDEF ASM_VERSION}
25304 function SeekMemStream( Strm: PStream; MoveTo: Integer; MoveFrom: TMoveMethod ): DWORD;
25306 PUSH EBX
25307 MOV EBX, EDX
25308 AND ECX, $FF
25309 LOOP @@not_from_cur
25310 ADD EBX, [EAX].TStream.fData.fPosition
25311 @@not_from_cur:
25312 LOOP @@not_from_end
25313 ADD EBX, [EAX].TStream.fData.fSize
25314 @@not_from_end:
25315 CMP EBX, [EAX].TStream.fData.fSize
25316 JLE @@space_ok
25317 PUSH EAX
25318 MOV EDX, EBX
25319 CALL TStream.SetSize
25320 POP EAX
25321 @@space_ok:
25322 XCHG EAX, EBX
25323 MOV [EBX].TStream.fData.fPosition, EAX
25324 POP EBX
25325 end;
25326 {$ELSE ASM_VERSION} //Pascal
25327 function SeekMemStream( Strm: PStream; MoveTo: Integer; MoveFrom: TMoveMethod ): DWORD;
25328 var NewPos: DWORD;
25329 begin
25330 case MoveFrom of
25331 spBegin: NewPos := MoveTo;
25332 spCurrent: NewPos := Strm.fData.fPosition + DWORD( MoveTo );
25333 else //spEnd:
25334 NewPos := Strm.fData.fSize + DWORD( MoveTo );
25335 end;
25336 if NewPos > Strm.fData.fSize then
25337 Strm.SetSize( NewPos );
25338 Strm.fData.fPosition := NewPos;
25339 Result := NewPos;
25340 end;
25341 {$ENDIF ASM_VERSION}
25342 //[END SeekMemStream]
25344 //[function GetSizeMemStream]
25345 function GetSizeMemStream( Strm: PStream ): DWORD;
25346 begin
25347 Result := Strm.fData.fSize;
25348 end;
25350 //[PROCEDURE SetSizeMemStream]
25351 {$IFDEF ASM_VERSION}
25352 procedure SetSizeMemStream( Strm: PStream; NewSize: DWORD );
25354 CMP [EAX].TStream.fData.fCapacity, EDX
25355 JGE @@cap_ok
25356 PUSH EDX
25357 PUSH EAX
25358 MOV ECX, [EAX].TStream.fMemory
25359 JECXZ @@get_mem
25360 TEST EDX, EDX
25361 JZ @@free_mem
25362 LEA EAX, [EAX].TStream.fMemory
25363 CALL System.@ReallocMem
25364 JMP @@1
25365 @@get_mem:
25366 XCHG EAX, EDX
25367 CALL System.@GetMem
25368 XCHG EDX, EAX
25369 POP EAX
25370 MOV [EAX].TStream.fMemory, EDX
25371 JMP @@2
25372 @@free_mem:
25373 XCHG EDX, [EAX].TStream.fMemory
25374 XCHG EAX, EDX
25375 CALL System.@FreeMem
25376 @@1:
25377 POP EAX
25378 @@2:
25379 POP EDX
25381 @@cap_ok:
25382 MOV [EAX].TStream.fData.fSize, EDX
25383 CMP [EAX].TStream.fData.fPosition, EDX
25384 JLE @@exit
25385 MOV [EAX].TStream.fData.fPosition, EDX
25386 @@exit:
25387 end;
25388 {$ELSE ASM_VERSION} //Pascal
25389 procedure SetSizeMemStream( Strm: PStream; NewSize: DWORD );
25390 var S: PStream;
25391 begin
25392 S := Strm;
25393 if S.fData.fCapacity < NewSize then
25394 begin
25395 if S.fMemory = nil then
25396 begin
25397 if NewSize <> 0 then
25398 GetMem( S.fMemory, NewSize );
25400 else
25401 if NewSize = 0 then
25402 begin
25403 FreeMem( S.fMemory );
25404 S.fMemory := nil;
25406 else
25407 ReallocMem( S.fMemory, NewSize );
25408 S.fData.fCapacity := NewSize;
25409 end;
25410 S.fData.fSize := NewSize;
25411 if S.fData.fPosition > S.fData.fSize then
25412 S.fData.fPosition := S.fData.fSize;
25413 end;
25414 {$ENDIF ASM_VERSION}
25415 //[END SetSizeMemStream]
25417 //[FUNCTION ReadMemStream]
25418 {$IFDEF ASM_VERSION}
25419 function ReadMemStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
25421 PUSH EBX
25422 XCHG EBX, EAX
25423 MOV EAX, [EBX].TStream.fData.fPosition
25424 ADD EAX, ECX
25425 CMP EAX, [EBX].TStream.fData.fSize
25426 JLE @@count_ok
25427 MOV ECX, [EBX].TStream.fData.fSize
25428 SUB ECX, [EBX].TStream.fData.fPosition
25429 @@count_ok:
25430 PUSH ECX
25431 MOV EAX, [EBX].TStream.fMemory
25432 ADD EAX, [EBX].TStream.fData.fPosition
25433 CALL System.Move
25434 POP EAX
25435 ADD [EBX].TStream.fData.fPosition, EAX
25436 POP EBX
25437 end;
25438 {$ELSE ASM_VERSION} //Pascal
25439 function ReadMemStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
25440 var S: PStream;
25441 begin
25442 S := Strm;
25443 if Count + S.fData.fPosition > S.fData.fSize then
25444 Count := S.fData.fSize - S.fData.fPosition;
25445 Result := Count;
25446 Move( Pointer( DWORD(S.fMemory) + S.fData.fPosition )^, Buffer, Result );
25447 Inc( S.fData.fPosition, Result );
25448 end;
25449 {$ENDIF ASM_VERSION}
25450 //[END ReadMemStream]
25452 //[FUNCTION WriteMemStream]
25453 {$IFDEF ASM_VERSION}
25454 function WriteMemStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
25456 PUSH EBX
25457 XCHG EBX, EAX
25458 MOV EAX, [EBX].TStream.fData.fPosition
25459 ADD EAX, ECX
25460 CMP EAX, [EBX].TStream.fData.fSize
25461 PUSH EDX
25462 PUSH ECX
25463 JLE @@count_ok
25464 XCHG EDX, EAX
25465 MOV EAX, EBX
25466 CALL TStream.SetSize
25467 @@count_ok:
25468 POP ECX
25469 POP EAX
25470 MOV EDX, [EBX].TStream.fMemory
25471 ADD EDX, [EBX].TStream.fData.fPosition
25472 PUSH ECX
25473 CALL System.Move
25474 POP EAX
25475 ADD [EBX].TStream.fData.fPosition, EAX
25476 POP EBX
25477 end;
25478 {$ELSE ASM_VERSION} //Pascal
25479 function WriteMemStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
25480 var S: PStream;
25481 begin
25482 S := Strm;
25483 if Count + S.fData.fPosition > S.fData.fSize then
25484 S.SetSize( S.fData.fPosition + Count );
25485 Result := Count;
25486 Move( Buffer, Pointer( DWORD(S.fMemory) + S.fData.fPosition )^, Result );
25487 Inc( S.fData.fPosition, Result );
25488 end;
25489 {$ENDIF ASM_VERSION}
25490 //[END WriteMemStream]
25492 //[PROCEDURE CloseMemStream]
25493 {$IFDEF ASM_VERSION}
25494 procedure CloseMemStream( Strm: PStream );
25496 MOV ECX, [EAX].TStream.fMemory
25497 JECXZ @@exit
25498 XCHG EAX, ECX
25499 CALL System.@FreeMem
25500 @@exit:
25501 end;
25502 {$ELSE ASM_VERSION} //Pascal
25503 procedure CloseMemStream( Strm: PStream );
25504 var S: PStream;
25505 begin
25506 S := Strm;
25507 if S.fMemory <> nil then
25508 FreeMem( S.fMemory );
25509 end;
25510 {$ENDIF ASM_VERSION}
25511 //[END CloseMemStream]
25513 const
25514 BaseFileMethods: TStreamMethods = (
25515 fSeek: SeekFileStream;
25516 fGetSiz: GetSizeFileStream;
25517 fSetSiz: DummySetSize;
25518 fRead: DummyReadWrite;
25519 fWrite: DummyReadWrite;
25520 fClose: CloseFileStream;
25521 fCustom: nil;
25524 MemoryMethods: TStreamMethods = (
25525 fSeek: SeekMemStream;
25526 fGetSiz: GetSizeMemStream;
25527 fSetSiz: SetSizeMemStream;
25528 fRead: ReadMemStream;
25529 fWrite: WriteMemStream;
25530 fClose: CloseMemStream;
25531 fCustom: nil;
25534 // by Roman Vorobets:
25535 //[procedure SetSizeFileStream]
25536 procedure SetSizeFileStream( Strm: PStream; NewSize: DWORD );
25538 P: DWORD;
25539 begin
25540 P:=Strm.Position;
25541 Strm.Position:=NewSize;
25542 SetEndOfFile(Strm.Handle);
25543 if P < NewSize then
25544 Strm.Position:=P;
25545 end;
25547 //[function NewFileStream]
25548 function NewFileStream( const FileName: String; Options: DWORD ): PStream;
25549 begin
25550 Result := _NewStream( BaseFileMethods );
25551 Result.fMethods.fRead := ReadFileStream;
25552 Result.fMethods.fWrite := WriteFileStream; // not WriteStreamEOF, Àëåêñåé Øóâàëîâ
25553 Result.fMethods.fSetSiz := SetSizeFileStream;
25554 Result.fData.fHandle := FileCreate( FileName, Options );
25555 end;
25557 //[FUNCTION NewReadFileStream]
25558 {$IFDEF ASM_VERSION}
25559 function NewReadFileStream( const FileName: String ): PStream;
25561 PUSH EBX
25562 XCHG EBX, EAX
25563 MOV EAX, offset[BaseFileMethods]
25564 CALL _NewStream
25565 MOV [EAX].TStream.fMethods.fRead, offset[ReadFileStream]
25566 XCHG EBX, EAX
25567 MOV EDX, ofOpenRead or ofOpenExisting or ofShareDenyWrite
25568 CALL FileCreate
25569 MOV [EBX].TStream.fData.fHandle, EAX
25570 XCHG EAX, EBX
25571 POP EBX
25572 end;
25573 {$ELSE ASM_VERSION} //Pascal
25574 function NewReadFileStream( const FileName: String ): PStream;
25575 begin
25576 Result := _NewStream( BaseFileMethods );
25577 Result.fMethods.fRead := ReadFileStream;
25578 Result.fData.fHandle := FileCreate( FileName,
25579 ofOpenRead or ofShareDenyWrite or ofOpenExisting );
25580 end;
25581 {$ENDIF ASM_VERSION}
25582 //[END NewReadFileStream]
25584 //[FUNCTION NewWriteFileStream]
25585 {$IFDEF ASM_VERSION}
25586 function NewWriteFileStream( const FileName: String ): PStream;
25588 PUSH EBX
25589 XCHG EBX, EAX
25590 MOV EAX, offset[BaseFileMethods]
25591 CALL _NewStream
25592 MOV [EAX].TStream.fMethods.fWrite, offset[WriteFileStreamEOF]
25593 MOV [EAX].TStream.fMethods.fSetSiz, offset[SetSizeFileStream]
25594 XCHG EBX, EAX
25595 MOV EDX, ofOpenWrite or ofOpenAlways or ofShareDenyWrite
25596 CALL FileCreate
25597 MOV [EBX].TStream.fData.fHandle, EAX
25598 XCHG EAX, EBX
25599 POP EBX
25600 end;
25601 {$ELSE ASM_VERSION} //Pascal
25602 function NewWriteFileStream( const FileName: String ): PStream;
25603 begin
25604 Result := _NewStream( BaseFileMethods );
25605 Result.fMethods.fWrite := WriteFileStreamEOF;
25606 Result.fMethods.fSetSiz := SetSizeFileStream;
25607 Result.fData.fHandle := FileCreate( FileName,
25608 //ofOpenWrite or ofCreateAlways );
25609 ofOpenWrite or ofOpenAlways or ofShareDenyWrite );
25610 end;
25611 {$ENDIF ASM_VERSION}
25612 //[END NewWriteFileStream]
25614 //[FUNCTION NewReadWriteFileStream]
25615 {$IFDEF ASM_noVERSION}
25616 function NewReadWriteFileStream( const FileName: String ): PStream;
25618 PUSH EBX
25619 XCHG EBX, EAX
25620 MOV EAX, offset[BaseFileMethods]
25621 CALL _NewStream
25622 MOV [EAX].TStream.fMethods.fRead, offset[ReadFileStream]
25623 MOV [EAX].TStream.fMethods.fWrite, offset[WriteFileStream]
25624 MOV [EAX].TStream.fMethods.fSetSiz, offset[SetSizeFileStream]
25625 XCHG EBX, EAX
25627 PUSH EAX
25628 CALL FileExists
25629 MOV EDX, ofOpenReadWrite or ofCreateAlways or ofShareDenyWrite
25630 ADD DH, AL // $200 (ofCreateAlways) -> $300 (ofCreateExisting)
25631 POP EAX
25633 CALL FileCreate
25634 MOV [EBX].TStream.fData.fHandle, EAX
25635 XCHG EAX, EBX
25636 POP EBX
25637 end;
25638 {$ELSE ASM_VERSION} //Pascal
25639 function NewReadWriteFileStream( const FileName: String ): PStream;
25640 var Creation: DWORD;
25641 begin
25642 Result := _NewStream( BaseFileMethods );
25643 Result.fMethods.fRead := ReadFileStream;
25644 Result.fMethods.fWrite := WriteFileStream;
25645 Result.fMethods.fSetSiz := SetSizeFileStream;
25646 Creation := ofCreateAlways;
25647 if FileExists( FileName ) then Creation := ofOpenExisting;
25648 Result.fData.fHandle := FileCreate( FileName,
25649 ofOpenReadWrite or Creation or ofShareDenyWrite );
25650 end;
25651 {$ENDIF ASM_VERSION}
25652 //[END NewReadWriteFileStream]
25654 //[function NewMemoryStream]
25655 function NewMemoryStream: PStream;
25656 begin
25657 Result := _NewStream( MemoryMethods );
25658 end;
25660 //[FUNCTION WriteExMemoryStream]
25661 {$IFDEF ASM_VERSION}
25662 function WriteExMemoryStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
25664 PUSH EBX
25665 XCHG EBX, EAX
25666 MOV EAX, [EBX].TStream.fData.fSize
25667 SUB EAX, [EBX].TStream.fData.fPosition
25668 CMP EAX, ECX
25669 JGE @@1
25670 XCHG ECX, EAX
25671 @@1:
25672 PUSH EDX
25673 PUSH ECX
25674 JLE @@count_ok
25675 XCHG EDX, EAX
25676 MOV EAX, EBX
25677 CALL TStream.SetSize
25678 @@count_ok:
25679 POP ECX
25680 POP EAX
25681 MOV EDX, [EBX].TStream.fMemory
25682 ADD EDX, [EBX].TStream.fData.fPosition
25683 PUSH ECX
25684 CALL System.Move
25685 POP EAX
25686 ADD [EBX].TStream.fData.fPosition, EAX
25687 POP EBX
25688 end;
25689 {$ELSE ASM_VERSION}
25690 function WriteExMemoryStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
25691 var S: PStream;
25692 begin
25693 S := Strm;
25694 if Count + S.fData.fPosition > S.fData.fSize then
25695 Count := S.fData.fSize - S.fData.fPosition;
25696 Result := Count;
25697 Move( Buffer, Pointer( DWORD(S.fMemory) + S.fData.fPosition )^, Result );
25698 Inc( S.fData.fPosition, Result );
25699 end;
25700 {$ENDIF ASM_VERSION}
25701 //[END WriteExMemoryStream]
25703 //[procedure DummyClose_ExMemStream]
25704 procedure DummyClose_ExMemStream( Strm: PStream );
25705 begin
25706 // nothing to do - ignore call (memory is not released by any way)
25707 end;
25709 //[function NewExMemoryStream]
25710 function NewExMemoryStream( ExistingMem: Pointer; Size: DWORD ): PStream;
25711 begin
25712 Result := NewMemoryStream;
25713 Result.fMemory := ExistingMem;
25714 Result.fData.fCapacity := Size;
25715 Result.fData.fSize := Size;
25716 Result.fMethods.fWrite := WriteExMemoryStream;
25717 Result.fMethods.fSetSiz := DummySetSize;
25718 Result.fMethods.fClose := DummyClose_ExMemStream;
25719 end;
25722 //[function Stream2Stream]
25723 function Stream2Stream( Dst, Src: PStream; Count: DWORD ): DWORD;
25724 var Buf: Pointer;
25725 begin
25726 if Src.fMemory <> nil then
25727 begin
25728 if Src.fData.fPosition + Count > Src.fData.fSize then
25729 Count := Src.fData.fSize - Src.fData.fPosition;
25730 Result := Dst.Write( Pointer(DWORD(Src.fMemory)+Src.fData.fPosition)^,
25731 Count );
25732 Inc( Src.fData.fPosition, Result );
25734 else
25735 if Dst.fMemory <> nil then
25736 begin
25737 if Dst.fData.fPosition + Count > Dst.fData.fSize then
25738 Dst.SetSize( Dst.fData.fPosition + Count );
25739 Result := Src.Read( Pointer( DWORD( Dst.fMemory ) + Dst.fData.fPosition )^,
25740 Count );
25741 Inc( Dst.fData.fPosition, Result );
25743 else
25744 begin
25745 GetMem( Buf, Count );
25746 Count := Src.Read( Buf^, Count );
25747 Result := Dst.Write( Buf^, Count );
25748 FreeMem( Buf );
25749 end;
25750 end;
25752 //[function Stream2StreamEx]
25753 function Stream2StreamEx( Dst, Src: PStream; Count: DWORD ): DWORD;
25754 begin
25755 Result := Stream2StreamExBufSz( Dst, Src, Count, 65536 );
25756 end;
25758 //[function Stream2StreamExBufSz]
25759 function Stream2StreamExBufSz( Dst, Src: PStream; Count, BufSz: DWORD ): DWORD;
25761 buf:pointer;
25762 rd, wr:dword;
25763 begin
25764 if count=0 then result:=0 else
25765 begin
25766 result:=0;
25767 BufSz := Min( BufSz, Count );
25768 if BufSz = 0 then BufSz := Count;
25769 getmem(buf,BufSz);
25770 repeat
25771 if count<BufSz then rd:=count else rd:=BufSz;
25772 rd:=src.read(buf^,rd);
25773 wr := dst.write(buf^,rd);
25774 inc(result,wr);
25775 dec(Count, rd);
25776 until (rd<>BufSz) or (Count=0);
25777 freemem(buf);
25778 end;
25779 end;
25781 //[FUNCTION Resource2Stream]
25782 {$IFDEF ASM_VERSION}
25783 function Resource2Stream( DestStrm : PStream; Inst : HInst;
25784 ResName : PChar; ResType : PChar ): Integer;
25786 PUSH EBX
25787 PUSH ESI
25788 MOV EBX, EDX // EBX = Inst
25789 PUSH EAX // DestStrm
25790 PUSH ResType
25791 PUSH ECX
25792 PUSH EDX
25793 CALL FindResource
25794 TEST EAX, EAX
25795 JZ @@exit0
25797 PUSH EAX
25798 PUSH EBX
25799 PUSH EAX
25800 PUSH EBX
25801 CALL SizeofResource
25802 XCHG EBX, EAX
25803 CALL LoadResource
25804 TEST EAX, EAX
25805 JZ @@exit0
25806 XCHG ESI, EAX
25808 PUSH ESI
25809 CALL GlobalLock
25810 TEST EAX, EAX
25811 JNZ @@P_ok
25813 CALL GetLastError
25814 CMP EAX, ERROR_INVALID_HANDLE
25815 JNZ @@exit_00
25816 MOV EAX, ESI
25818 @@P_ok:
25819 XCHG EDX, EAX
25820 POP EAX // DestStrm
25821 PUSH EDX
25822 MOV ECX, EBX
25823 CALL TStream.Write
25825 //EAX = Result (length of written data)
25826 XCHG EBX, EAX
25827 POP EAX
25828 CMP ESI, EAX
25829 JE @@not_unlock
25831 PUSH ESI
25832 CALL GlobalUnlock
25833 @@not_unlock:
25834 XCHG EAX, EBX
25835 JMP @@exit
25837 @@exit_00:
25838 XOR EAX, EAX
25839 @@exit0:
25840 POP ECX
25841 @@exit:
25842 POP ESI
25843 POP EBX
25844 end;
25845 {$ELSE ASM_VERSION} //Pascal
25846 function Resource2Stream( DestStrm : PStream; Inst : HInst;
25847 ResName : PChar; ResType : PChar ): Integer;
25848 var R : HRSRC;
25849 G : HGlobal;
25850 P : PChar;
25851 Sz : DWORD;
25852 E : Integer;
25853 begin
25854 Result := 0;
25855 R := FindResource( Inst, ResName, ResType );
25856 if R <> 0 then
25857 begin
25858 Sz := SizeofResource( Inst, R );
25859 G := LoadResource( Inst, R );
25860 if G <> 0 then
25861 begin
25862 P := GlobalLock( G );
25863 if P = nil then
25864 begin
25865 E := GetLastError;
25866 if E = ERROR_INVALID_HANDLE then
25867 P := Pointer( G )
25868 else
25869 Exit;
25870 end;
25871 Result := DestStrm.Write( P^, Sz );
25872 if P <> Pointer( G ) then
25873 GlobalUnlock( G );
25874 //FreeResource( G );
25875 { from Win32.hlp: "You do not need to call the FreeResource
25876 function to free a resource loaded by using the LoadResource
25877 function." }
25878 end;
25879 end;
25880 end;
25881 {$ENDIF ASM_VERSION}
25882 //[END Resource2Stream]
25895 ///////////////////////////////////////////////////////////////////////////
25898 // I N I - F I L E S
25901 ///////////////////////////////////////////////////////////////////////////
25904 { TIniFile }
25906 {$IFDEF ASM_VERSION}
25907 //[destructor TIniFile.Destroy]
25908 destructor TIniFile.Destroy;
25909 asm //cmd //opd
25910 PUSH EAX
25911 LEA EDX, [EAX].fFileName
25912 PUSH EDX
25913 LEA EAX, [EAX].fSection
25914 CALL System.@LStrClr
25915 POP EAX
25916 CALL System.@LStrClr
25917 POP EAX
25918 CALL TObj.Destroy
25919 end;
25920 {$ELSE ASM_VERSION} //Pascal
25921 destructor TIniFile.Destroy;
25922 begin
25923 fFileName := '';
25924 fSection := '';
25925 inherited;
25926 end;
25927 {$ENDIF ASM_VERSION}
25929 {$IFNDEF _D5orHigher}
25930 // Place here correct definition for WritePrivateProfileStruct
25931 // and GetPrivateProfileStruct (a bug in Delphi2, Delphi3 and Delphi4)
25932 //[API WritePrivateProfileStruct]
25933 function WritePrivateProfileStruct(lpszSection, lpszKey: PChar;
25934 lpStruct: Pointer; uSizeStruct: UINT; szFile: PChar): BOOL; stdcall;
25935 external kernel32 name 'WritePrivateProfileStructA';
25936 //[API GetPrivateProfileStruct]
25937 function GetPrivateProfileStruct(lpszSection, lpszKey: PAnsiChar;
25938 lpStruct: Pointer; uSizeStruct: UINT; szFile: PAnsiChar): BOOL; stdcall;
25939 external kernel32 name 'GetPrivateProfileStructA';
25941 // + by Slava A. Gavrik:
25942 ////////////////////////////////////////////////////////////////////////////
25943 //[function WritePrivateProfileSection]
25944 function WritePrivateProfileSection(lpAppName, lpString,
25945 lpFileName: PChar): BOOL; stdcall;
25946 external kernel32 name 'WritePrivateProfileSectionA';
25947 //[function GetPrivateProfileSection]
25948 function GetPrivateProfileSection(lpAppName: PChar; lpReturnedString: PChar;
25949 nSize: DWORD; lpFileName: PChar): DWORD; stdcall;
25950 external kernel32 name 'GetPrivateProfileSectionA';
25952 //[function GetPrivateProfileSectionNames]
25953 function GetPrivateProfileSectionNames(lpszReturnBuffer: PChar; nSize:
25954 DWORD;
25955 lpFileName: PChar): DWORD; stdcall;
25956 external kernel32 name 'GetPrivateProfileSectionNamesA';
25957 ////////////////////////////////////////////////////////////////////////////
25958 {$ENDIF}
25961 //[procedure TIniFile.ClearAll]
25962 procedure TIniFile.ClearAll;
25963 begin
25964 WritePrivateProfileString( nil, nil, nil,
25965 PChar( fFileName ) );
25966 end;
25968 //[procedure TIniFile.ClearKey]
25969 procedure TIniFile.ClearKey(const Key: String);
25970 begin
25971 WritePrivateProfileString( PChar( fSection ), PChar( Key ), nil,
25972 PChar( fFileName ) );
25973 end;
25975 //[procedure TIniFile.ClearSection]
25976 procedure TIniFile.ClearSection;
25977 begin
25978 WritePrivateProfileString( PChar( fSection ), nil, nil,
25979 PChar( fFileName ) );
25980 end;
25982 //[function TIniFile.ValueBoolean]
25983 function TIniFile.ValueBoolean(const Key: String; Value: Boolean): Boolean;
25984 begin
25985 if fMode = ifmRead then
25986 Result := GetPrivateProfileInt( PChar( fSection ), PChar( Key ),
25987 Integer( Value ), PChar( fFileName ) ) <> 0
25988 else
25989 begin
25990 WritePrivateProfileString( PChar( fSection ), PChar( Key ),
25991 PChar( Int2Str( Integer( Value ) ) ), PChar( fFileName ) );
25992 Result := Value;
25993 end;
25994 end;
25996 //[function TIniFile.ValueData]
25997 function TIniFile.ValueData(const Key: String; Value: Pointer;
25998 Count: Integer): Boolean;
25999 begin
26000 if fMode = ifmRead then
26001 Result := GetPrivateProfileStruct( PChar( fSection ), PChar( Key ),
26002 Value, Count, PChar( fFileName ) )
26003 else
26004 Result := WritePrivateProfileStruct( PChar( fSection ), PChar( Key ),
26005 Value, Count, PChar( fFileName ) );
26006 end;
26008 //[function TIniFile.ValueInteger]
26009 function TIniFile.ValueInteger(const Key: String; Value: Integer): Integer;
26010 begin
26011 if fMode = ifmRead then
26012 Result := GetPrivateProfileInt( PChar( fSection ), PChar( Key ),
26013 Integer( Value ), PChar( fFileName ) )
26014 else
26015 begin
26016 Result := Value;
26017 WritePrivateProfileString( PChar( fSection ), PChar( Key ),
26018 PChar( Int2Str( Value ) ), PChar( fFileName ) );
26019 end;
26020 end;
26022 //[function TIniFile.ValueString]
26023 function TIniFile.ValueString(const Key, Value: String): String;
26025 Buffer: array[0..2047] of Char;
26026 begin
26027 if fMode = ifmRead then
26028 begin
26029 Buffer[ 0 ] := #0;
26030 GetPrivateProfileString(PChar(fSection),
26031 PChar(Key), PChar(Value), Buffer, SizeOf(Buffer), PChar(fFileName));
26032 Result := Buffer;
26034 else
26035 begin
26036 Result := Value;
26037 WritePrivateProfileString( PChar( fSection ), PChar( Key ),
26038 PChar( Value ), PChar( fFileName ) );
26039 end;
26040 end;
26042 //[function OpenIniFile]
26043 function OpenIniFile( const FileName: String ): PIniFile;
26044 begin
26046 New( Result, Create );
26047 {+}{++}(*Result := PIniFile.Create;*){--}
26048 Result.fFileName := FileName;
26049 end;
26051 /////////////////////////////////////////////////// GetSectionNames, SectionData
26052 // - by Vyacheslav A. Gavrik :
26054 const
26055 IniBufferSize = 32767;
26056 IniBufferStrSize = IniBufferSize+4; /// äëÿ ìàõèíàöèé :)
26058 {$IFDEF ASM_VERSION}
26059 //[procedure _FillStrList]
26060 procedure _FillStrList; // Ýòà ÷àñòü êîäà îáùàÿ äëÿ äâóõ ñëåäóþùèõ ïðîöåäóð
26062 ///////////////////////////////
26063 OR EAX,0
26064 JE @@EXIT //ERROR
26065 // LEA EAX,[EAX-IniBufferSize]
26066 // JE @@EXIT
26067 // âîçìîæíà íåõâàòêà Áóôåðà... â ïðèíöèïå íå îøèáêà :)
26068 // âîçâðàùàåì ÷òî âëåçëî...
26069 //////////////////////////////
26070 @@LOOP:
26071 LEA EAX,[ESI+4]
26072 CALL StrLen
26073 MOV [ESI],EAX
26074 LEA EDX,[ESI+4]
26075 INC EAX
26076 ADD ESI,EAX
26078 MOV EAX,EDI
26080 CALL TStrList.ADD
26082 CMP byte ptr [ESI+4],0
26083 JNE @@LOOP
26085 @@EXIT:
26086 POP EAX
26087 CALL System.@FreeMem
26090 POP ECX
26091 POP EBX
26092 POP EDI
26093 POP ESI
26094 end;
26097 //[procedure TIniFile.GetSectionNames]
26098 procedure TIniFile.GetSectionNames(Names: PStrList);
26100 PUSH ESI
26101 PUSH EDI
26102 PUSH EBX
26103 PUSH ECX
26105 MOV EBX,EAX
26106 MOV EAX, IniBufferStrSize
26107 MOV EDI,EDX
26109 CALL System.@GetMem
26110 MOV ESI,EAX
26111 PUSH EAX
26113 PUSH [EBX].fFileName
26114 MOV EAX,IniBufferSize
26115 PUSH EAX
26117 LEA EAX,[ESI+4]
26118 PUSH EAX
26120 CALL GetPrivateProfileSectionNames
26121 JMP _FillStrList
26122 end;
26124 //[procedure TIniFile.SectionData]
26125 procedure TIniFile.SectionData(Names: PStrList);
26127 PUSH ESI
26128 PUSH EDI
26129 PUSH EBX
26130 PUSH ECX
26132 MOV EBX,EAX
26133 MOV EAX, IniBufferStrSize
26134 MOV EDI,EDX
26136 CALL System.@GetMem
26137 MOV ESI,EAX
26138 PUSH EAX
26140 OR [EBX].fMode,0
26141 JNE @@DOWrite
26143 PUSH [EBX].fFileName
26144 MOV EAX,IniBufferSize
26145 PUSH EAX
26147 LEA EAX,[ESI+4]
26148 PUSH EAX
26149 PUSH [EBX].fSection
26151 CALL GetPrivateProfileSection
26152 JMP _FillStrList
26154 @@DOWrite:
26156 PUSH EBX
26157 PUSH ESI
26158 PUSH EDX
26159 PUSH EBP
26161 MOV EDX,0
26162 MOV EBP,[EDI].TStrList.fCount
26163 MOV EBX,IniBufferSize-2 // îñòàâèì ìåñòî äëÿ #0#0
26165 {ECM+++>} OR EBP,EBP // otherwise GetPChars when StrList.Count = 0 crashed
26167 @@LOOP:
26168 JE @@ENDLOOP
26170 OR EBX,EBX
26171 JE @@ENDLOOP
26173 PUSH EDX
26174 MOV EAX,EDI
26175 CALL TStrList.GetPChars
26177 PUSH EAX
26178 CALL StrLen
26179 POP EAX
26181 XOR ECX,-1
26182 MOV EDX,ESI
26184 SUB EBX,ECX
26185 JA @@L1
26186 ADD ECX,EBX
26187 XOR EBX,EBX
26188 @@L1:
26190 ADD ESI,ECX
26192 CALL MOVE
26193 @@L2:
26194 POP EDX
26195 INC EDX
26196 DEC EBP
26197 JMP @@LOOP
26198 @@ENDLOOP:
26199 MOV WORD PTR [ESI],0
26201 POP EBP
26202 POP EDX
26203 POP ESI
26204 POP EBX
26205 ///////////////////////////////////
26206 MOV EAX,EBX // íîäî î÷èùàòü
26207 CALL ClearSection
26208 //////////////////////////////////
26210 PUSH [EBX].fFileName
26211 PUSH ESI
26212 PUSH [EBX].fSection
26214 CALL WritePrivateProfileSection
26216 POP EAX
26217 CALL System.@FreeMem
26219 POP ECX
26220 POP EBX
26221 POP EDI
26222 POP ESI
26224 end;
26225 {$ELSE ASM_VERSION} //Pascal
26227 //[procedure TIniFile.GetSectionNames]
26228 procedure TIniFile.GetSectionNames(Names: PStrList);
26230 i:integer;
26231 Pc:PChar;
26232 PcEnd:PChar;
26233 Buffer:Pointer;
26234 begin
26235 GetMem(Buffer,IniBufferSize);
26236 Pc:=Buffer;
26237 i := GetPrivateProfileSectionNames(Buffer, IniBufferSize, PChar(fFileName));
26238 PcEnd:=Pc+i;
26239 repeat
26240 Names.Add(Pc);
26241 Pc:=PC+Length(PC)+1;
26242 until PC>=PcEnd;
26243 FreeMem(Buffer);
26244 end;
26246 //[procedure TIniFile.SectionData]
26247 procedure TIniFile.SectionData(Names: PStrList);
26249 i:integer;
26250 Pc:PChar;
26251 PcEnd:PChar;
26252 Buffer:Pointer;
26253 begin
26254 GetMem(Buffer,IniBufferSize);
26255 Pc:=Buffer;
26256 if fMode = ifmRead then
26257 begin
26258 i:=GetPrivateProfileSection(PChar(fSection), Buffer, IniBufferSize, PChar(fFileName));
26259 PcEnd:=Pc+i;
26260 while PC < PcEnd do // Chg by ECM from REPEAT-UNTIL: i=0 (empty section) => Names.Count=1
26261 begin
26262 Names.Add(Pc);
26263 Pc:=PC+Length(PC)+1;
26264 end;
26265 end else
26266 begin
26267 for i:= 0 to Names.Count-1 do
26268 begin
26269 StrCopy(Pc,Names.ItemPtrs[i]);
26270 Pc:=PC+Length(PC)+1;
26271 end;
26272 Pc[0]:=#0;
26273 ClearSection;
26274 WritePrivateProfileSection(PChar(fSection), Buffer, PChar(fFileName));
26276 end;
26277 FreeMem(Buffer);
26278 end;
26279 {$ENDIF ASM_VERSION}
26281 //////////////////////////////////////////////////////////////////////
26293 /////////////////////////////////////////////////////////////////////////
26296 // M E N U
26299 /////////////////////////////////////////////////////////////////////////
26301 { -- Menu implementation -- }
26303 //[FUNCTION MakeAccelerator]
26304 {$IFDEF ASM_VERSION}
26305 function MakeAccelerator( fVirt: Byte; Key: Word ): TMenuAccelerator;
26307 MOVZX EAX, AL
26308 PUSH EAX
26309 MOV [ESP+1], DX
26310 POP EAX
26311 end;
26312 {$ELSE ASM_VERSION} //Pascal
26313 function MakeAccelerator( fVirt: Byte; Key: Word ): TMenuAccelerator;
26314 begin
26315 Result.fVirt := fVirt;
26316 Result.Key := Key;
26317 end;
26318 {$ENDIF ASM_VERSION}
26319 //[END MakeAccelerator]
26321 //[FUNCTION GetAcceleratorText]
26322 function GetAcceleratorText( const Accelerator: TMenuAccelerator ): string;
26324 KeyName: array[0..255] of Char;
26326 procedure AddKeyName( Code: Integer );
26327 begin
26328 Code := MapVirtualKey(Code, 0);
26329 if Code = 0 then exit;
26330 if GetKeyNameText(Code shl 16, KeyName, SizeOf(KeyName)) > 0 then begin
26331 if Result <> '' then
26332 Result := Result + '+';
26333 Result := Result + KeyName;
26334 end;
26335 end;
26337 begin
26338 Result := '';
26339 with Accelerator do begin
26340 if fVirt and FCONTROL <> 0 then
26341 AddKeyName(VK_CONTROL);
26342 if fVirt and FSHIFT <> 0 then
26343 AddKeyName(VK_SHIFT);
26344 if fVirt and FALT <> 0 then
26345 AddKeyName(VK_ALT);
26346 if fVirt and $20 <> 0 then
26347 AddKeyName(VK_LWIN);
26348 if fVirt and $40 <> 0 then
26349 AddKeyName(VK_RWIN);
26351 AddKeyName(Key);
26352 end;
26353 end;
26354 //[END GetAcceleratorText]
26357 const
26358 MIDATA_CHECKITEM = $40000000;
26359 MIDATA_RADIOITEM = $80000000;
26361 //[function WndProcMenu]
26362 {$IFNDEF NEW_MENU_ACCELL}
26363 function WndProcMenu( Sender: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
26364 var M, M1: PMenu;
26365 Idx: Integer;
26366 Id: Integer;
26367 begin
26368 Result := False;
26369 if Msg.message = WM_COMMAND then
26370 begin
26371 if (Msg.lParam = 0) and (HIWORD( Msg.wParam ) <= 1) then
26372 begin
26373 M := PMenu( Sender.fMenuObj );
26374 while M <> nil do
26375 begin
26376 Id := LoWord( Msg.wParam );
26377 M1 := M.Items[ Id ];
26378 if M1 <> nil then
26379 begin
26380 Result := True;
26381 Rslt := 0;
26382 Idx := M.IndexOf( M1 );
26383 M.fByAccel := HiWord( Msg.wParam ) <> 0;
26384 if M1.FRadioGroup <> 0 then
26385 M1.RadioCheckItem
26386 else
26387 if M1.FIsCheckItem then
26388 M1.Checked := not M1.Checked;
26389 if Assigned(M1.FOnMenuItem) then
26390 M1.FOnMenuItem( M, Idx )
26391 else if Assigned( M.FOnMenuItem ) then
26392 M.FOnMenuItem( M, Idx );
26393 //M.FProcessed := True;
26394 break;
26395 end;
26396 M := M.fNextMenu;
26397 end;
26398 end;
26399 end;
26400 end;
26402 {$ELSE}
26404 function WndProcMenu( Sender: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
26406 function ProcessMenuItem(M: PMenu; Id: Integer): Boolean;
26408 M1: PMenu;
26409 Idx: Integer;
26410 begin
26411 M1 := M.Items[ Id ];
26412 Result := (M1 <> nil);
26413 if Result then
26414 begin
26415 Idx := M.IndexOf( M1 );
26416 M.fByAccel := HiWord( Msg.wParam ) <> 0;
26417 if M1.FRadioGroup <> 0 then
26418 M1.RadioCheckItem
26419 else
26420 if M1.FIsCheckItem then
26421 M1.Checked := not M1.Checked;
26422 if Assigned(M1.FOnMenuItem) then begin
26423 {$IFDEF USE_MENU_CURCTL} // fixed
26424 M.fCurCtl := Sender; // fixed
26425 {$ENDIF} // fixed
26426 M1.FOnMenuItem( M, Idx )
26428 else if Assigned( M.FOnMenuItem ) then
26429 M.FOnMenuItem( M, Idx );
26430 end;
26431 end;
26434 M: PMenu;
26435 Id: Integer;
26436 begin
26437 Result := False;
26438 if Msg.message = WM_COMMAND then
26439 if (Msg.lParam = 0) and (HIWORD( Msg.wParam ) <= 1) then begin
26440 Id := LoWord(Msg.wParam);
26441 M := PMenu(Sender.fAutoPopupMenu);
26442 if (M <> nil) and ProcessMenuItem(M, Id) then begin
26443 Result := True;
26444 Rslt := 0;
26446 else begin
26447 M := PMenu(Sender.fMenuObj);
26448 while M <> nil do begin
26449 if ProcessMenuItem(M, Id) then begin
26450 Result := True;
26451 Rslt := 0;
26452 Break;
26453 end;
26454 M := M.fNextMenu;
26455 end;
26456 end;
26457 end;
26458 end;
26459 {$ENDIF}
26462 var FDynamicMenuID: DWORD = $1000;
26464 //[function NewMenu]
26465 function NewMenu( AParent : PControl; MaxCmdReserve : DWORD; const Template : array of PChar;
26466 aOnMenuItem: TOnMenuItem ): PMenu;
26467 var M: PMenu;
26468 begin
26470 New( Result, Create );
26471 {+}{++}(*Result := PMenu.Create;*){--}
26472 Result.FVisible := TRUE;
26473 Result.FPopupFlags := TPM_LEFTALIGN or TPM_LEFTBUTTON;
26474 Result.FItems := NewList;
26475 Result.FOnMenuItem := aOnMenuItem;
26476 if (High(Template)>=0) and (Template[0] <> nil) then
26477 begin
26478 if (AParent <> nil) and (AParent.fMenuObj = nil) and not AParent.fIsControl then
26479 Result.FHandle := CreateMenu
26480 else
26481 Result.FHandle := CreatePopupMenu;
26482 Result.FillMenuItems( Result.FHandle, 0, Template );
26483 end;
26484 if assigned( AParent ) then
26485 begin
26486 Result.FControl := AParent;
26487 if AParent.fMenuObj <> nil then
26488 begin
26489 // add popup menu to the end of menu chain
26490 M := PMenu( AParent.fMenuObj );
26491 while M.fNextMenu <> nil do
26492 M := M.fNextMenu;
26493 M.fNextMenu := Result;
26495 else
26496 begin
26497 if not AParent.fIsControl then
26498 AParent.Menu := Result.FHandle;
26499 AParent.fMenuObj := Result;
26500 AParent.AttachProc( WndProcMenu );
26501 end;
26502 end;
26503 end;
26504 //[END NewMenu]
26506 //[function NewMenuEx]
26507 function NewMenuEx( AParent : PControl; FirstCmd : Integer; const Template : array of PChar;
26508 aOnMenuItems: array of TOnMenuItem ): PMenu;
26509 begin
26510 Result := NewMenu( AParent, FirstCmd, Template, nil );
26511 Result.AssignEvents( 0, aOnMenuItems );
26512 end;
26513 //[END NewMenuEx]
26515 { TMenu }
26517 const
26518 Breaks: array[ TMenuBreak ] of DWORD = ( 0, MFT_MENUBREAK, MFT_MENUBARBREAK );
26520 { + by AK - Andrzej Kubaszek }
26521 //[function MenuStructSize]
26522 function MenuStructSize: Integer;
26523 begin
26524 Result := 44;
26525 if not( WinVer in [wv31, wv95, wvNT] ) then
26526 Result := {48=} Sizeof( TMenuItemInfo );
26527 end;
26529 //[destructor TMenu.Destroy]
26530 destructor TMenu.Destroy;
26531 var Next, Prnt: PMenu;
26532 begin
26533 if Count > 0 then
26534 begin
26535 FItems.ReleaseObjects;
26536 FItems := NewList;
26537 end;
26538 if FParent <> nil then
26539 begin
26540 Prnt := FParent;
26541 FParent := nil;
26542 Next := Prnt.RemoveSubMenu( FId );
26543 Prnt.FItems.Remove( @ Self );
26544 if Next = nil then Exit;
26545 end;
26546 if (FControl <> nil) and (FControl.fMenu = FHandle) and (FHandle <> 0) then
26547 begin
26548 //if FControl.fHandle <> 0 then
26549 begin
26550 Windows.SetMenu( FControl.fHandle, 0 );
26551 // this removes main menu from window, but does not destroy it
26552 end;
26553 FControl.fMenu := 0;
26554 Next := PMenu( FControl.fMenuObj );
26555 while Next <> nil do
26556 begin
26557 if Next.fNextMenu = @Self then
26558 begin
26559 Next.fNextMenu := fNextMenu;
26560 break;
26561 end;
26562 Next := Next.fNextMenu;
26563 end;
26564 end;
26565 Next := fNextMenu;
26566 if FBitmap <> 0 then
26567 Bitmap := 0;
26568 if FHandle <> 0 then
26569 DestroyMenu( FHandle );
26570 FCaption := '';
26571 FItems.Free;
26572 inherited;
26573 Next.Free;
26574 // all later created (popup) menus (of the same control)
26575 // are destroyed too
26576 end;
26578 //[function TMenu.GetInfo]
26579 function TMenu.GetInfo( var MII: TMenuItemInfo ): Boolean;
26580 begin
26581 MII.cbSize := MenuStructSize;
26582 Result := GetMenuItemInfo( Parent.FHandle, FId, FALSE,
26583 Windows.PMenuitemInfo( @ MII )^ );
26584 end;
26586 //[procedure TMenu.RedrawFormMenuBar]
26587 procedure TMenu.RedrawFormMenuBar;
26588 var C: PControl;
26589 begin
26590 C := TopParent.FControl;
26591 if not AppletTerminated then
26592 if (C <> nil) and (Pointer( C.fMenuObj ) = Pointer( TopParent )) then
26593 DrawMenuBar( C.FHandle );
26594 end;
26596 //[function TMenu.SetInfo]
26597 function TMenu.SetInfo( var MII: TMenuItemInfo ): Boolean;
26598 var H: THandle;
26599 begin
26600 MII.cbSize := MenuStructSize;
26601 H := FHandle;
26602 if FParent <> nil then
26603 H := FParent.FHandle;
26604 Result := SetMenuItemInfo( H, FId, FALSE, Windows.PMenuitemInfo( @ MII )^ );
26605 if Result and ((FParent = nil) or (FParent.FParent = nil)) then {YS}
26606 RedrawFormMenuBar;
26607 end;
26609 //[function TMenu.SetTypeInfo]
26610 function TMenu.SetTypeInfo( var MII: TMenuItemInfo ): Boolean;
26611 begin
26612 if not FIsSeparator then
26613 begin
26614 if FBmpItem = 0 then
26615 MII.dwTypeData := PChar( FCaption )
26616 else
26617 MII.dwTypeData := Pointer( FBmpItem );
26618 MII.cch := Length( FCaption );
26619 end;
26620 Result := SetInfo( MII );
26621 end;
26623 //[function TMenu.GetTopParent]
26624 function TMenu.GetTopParent: PMenu;
26625 begin
26626 Result := @ Self;
26627 while Result.FParent <> nil do
26628 Result := Result.FParent;
26629 end;
26631 //[function TMenu.GetControl]
26632 function TMenu.GetControl: PControl;
26633 begin
26634 Result := TopParent.FControl;
26635 end;
26637 //[function TMenu.GetItems]
26638 function TMenu.GetItems( Id: HMenu ): PMenu;
26639 function SearchItems( ParentMenu: PMenu; var FromIdx: Integer ): PMenu;
26640 var I: Integer;
26641 begin
26642 Result := ParentMenu;
26643 if Id = HMenu( FromIdx ) then Exit;
26644 if (Id >= 4096) and (DWORD( ParentMenu.FId ) = Id) then Exit;
26645 if ParentMenu.FItems = nil then Exit;
26646 for I := 0 to ParentMenu.FItems.FCount-1 do
26647 begin
26648 Inc( FromIdx );
26649 Result := SearchItems( ParentMenu.FItems.Items[ I ], FromIdx );
26650 if Result <> nil then Exit;
26651 end;
26652 Result := nil;
26653 end;
26654 var I: Integer;
26655 begin
26656 I := -1;
26657 Result := SearchItems( @ Self, I );
26658 end;
26660 //[function TMenu.GetCount]
26661 function TMenu.GetCount: Integer;
26662 var I: Integer;
26663 SubM: PMenu;
26664 begin
26665 Result := FItems.FCount;
26666 for I := 0 to Result-1 do
26667 begin
26668 SubM := FItems.Items[ I ];
26669 Result := Result + SubM.Count;
26670 end;
26671 end;
26673 //[function TMenu.IndexOf]
26674 function TMenu.IndexOf( Item: PMenu ): Integer;
26675 function SearchMenu( ParentMenu: PMenu; var FromIdx: Integer ): PMenu;
26676 var I: Integer;
26677 begin
26678 Result := ParentMenu;
26679 if Result = Item then Exit;
26680 for I := 0 to ParentMenu.FItems.FCount-1 do
26681 begin
26682 Inc( FromIdx );
26683 Result := SearchMenu( ParentMenu.FItems.Items[ I ], FromIdx );
26684 if Result <> nil then Exit;
26685 end;
26686 Result := nil;
26687 end;
26688 begin
26689 Result := -1;
26690 if SearchMenu( @ Self, Result ) = nil then
26691 Result := -2;
26692 end;
26694 //[function TMenu.GetState]
26695 function TMenu.GetState( const Index: Integer ): Boolean;
26696 var MII: TMenuItemInfo;
26697 begin
26698 if FVisible then
26699 begin
26700 MII.fMask := MIIM_STATE;
26701 if GetInfo( MII ) then
26702 FSavedState := MII.fState;
26703 end;
26704 Result := LongBool( FSavedState and Index );
26705 if Index < 0 then
26706 Result := not Result;
26707 end;
26709 //[procedure TMenu.SetState]
26710 procedure TMenu.SetState( const Index: Integer; Value: Boolean );
26711 var MII: TMenuItemInfo;
26712 begin
26713 GetState( 0 );
26714 if Value xor (Index < 0) then
26715 FSavedState := FSavedState or DWORD( Index and $7FFFFFFF )
26716 else
26717 FSavedState := FSavedState and not DWORD( Index );
26718 if FVisible then
26719 begin
26720 MII.fMask := MIIM_STATE;
26721 if GetInfo( MII ) then
26722 begin
26723 MII.fState := FSavedState;
26724 SetInfo( MII );
26725 end;
26726 end;
26727 end;
26729 //[procedure TMenu.SetData]
26730 procedure TMenu.SetData( Value: Pointer );
26731 var MII: TMenuItemInfo;
26732 begin
26733 MII.fMask := MIIM_DATA;
26734 MII.dwItemData := DWORD( Value );
26735 SetInfo( MII );
26736 FData := Value;
26737 end;
26739 //[procedure TMenu.ClearBitmaps]
26740 procedure TMenu.ClearBitmaps;
26741 begin
26742 if FBitmap <> 0 then
26743 DeleteObject( FBitmap );
26744 if FBmpChecked <> 0 then
26745 DeleteObject( FBmpChecked );
26746 if FBmpItem <> 0 then
26747 DeleteObject( FBmpItem );
26748 end;
26750 //[procedure TMenu.SetBitmap]
26751 procedure TMenu.SetBitmap( Value: HBitmap );
26752 var MII: TMenuItemInfo;
26753 begin
26754 if not FClearBitmaps then
26755 begin
26756 FClearBitmaps := TRUE;
26757 Add2AutoFreeEx( ClearBitmaps );
26758 end;
26759 if Value = FBitmap then Exit;
26760 if FBitmap <> 0 then
26761 DeleteObject( FBitmap ); // seems not necessary.
26762 FBitmap := Value;
26763 MII.fMask := MIIM_CHECKMARKS;
26764 MII.hbmpChecked := FBmpChecked;
26765 MII.hbmpUnchecked := FBitmap;
26766 SetInfo( MII );
26767 end;
26769 //[procedure TMenu.SetBmpChecked]
26770 procedure TMenu.SetBmpChecked( Value: HBitmap );
26771 var MII: TMenuItemInfo;
26772 begin
26773 if not FClearBitmaps then
26774 begin
26775 FClearBitmaps := TRUE;
26776 Add2AutoFreeEx( ClearBitmaps );
26777 end;
26778 if Value = FBmpChecked then Exit;
26779 if FBmpChecked <> 0 then
26780 DeleteObject( FBmpChecked );
26781 FBmpChecked := Value;
26782 MII.fMask := MIIM_CHECKMARKS;
26783 MII.hbmpChecked := FBmpChecked;
26784 MII.hbmpUnchecked := FBitmap;
26785 SetInfo( MII );
26786 end;
26788 //[procedure TMenu.SetBmpItem]
26789 procedure TMenu.SetBmpItem( Value: HBitmap );
26790 var MII: TMenuItemInfo;
26791 begin
26792 if not FClearBitmaps then
26793 begin
26794 FClearBitmaps := TRUE;
26795 Add2AutoFreeEx( ClearBitmaps );
26796 end;
26797 if Value = FBmpItem then Exit;
26798 if FBmpItem <> 0 then
26799 DeleteObject( FBmpItem );
26800 FBmpItem := Value;
26801 if WinVer >= wv98 then {AK}
26802 begin {AK}
26803 MII.fMask := $80 {MIIM_BITMAP} ; {AK}
26804 MII.hbmpItem:=Value; {AK}
26805 end {AK}
26806 else {AK}
26807 begin//I haven't possibility to test it in Win95 {AK}
26808 MII.fType := MFT_BITMAP;
26809 MII.dwItemData := Value;
26810 end; {AK}
26811 SetInfo( MII );
26812 end;
26814 //[procedure TMenu.SetAccelerator]
26815 {$IFNDEF NEW_MENU_ACCELL}
26816 procedure TMenu.SetAccelerator(const Value: TMenuAccelerator);
26817 const MaxAccel = 1000;
26818 type TAccTab = array[0..10000] of TAccel;
26819 PAccTab = ^TAccTab;
26820 //TSetAcceleratorProc = procedure( Self_: PMenu; Idx: Integer; const Value: TMenuAccelerator );
26821 var AccTab: PAccTab;
26822 I, N : Integer;
26823 M, SubM: PMenu;
26824 C: PControl;
26825 Main: Boolean;
26826 begin
26827 //SetAcceleratorProc := TSetAcceleratorProc( MakeMethod( nil, @TMenu.SetAccelerator ).Code );
26828 if (FAccelerator.fVirt = Value.fVirt) and (FAccelerator.Key = Value.Key) then Exit;
26829 FAccelerator := Value;
26830 C := TopParent.FControl;
26831 if C = nil then Exit;
26832 if C.fAccelTable <> 0 then
26833 DestroyAcceleratorTable( C.fAccelTable );
26834 C.fAccelTable := 0;
26835 GetMem( AccTab, sizeof( TAccel ) * MaxAccel );
26836 N := 0;
26837 M := PMenu( C.fMenuObj );
26838 Main := TRUE;
26839 while M <> nil do
26840 begin
26841 if Main or M.Visible then
26842 begin
26843 for I := 0 to MaxInt-1 do
26844 begin
26845 SubM := M.Items[ I ];
26846 if SubM = nil then break;
26847 if SubM.FVisible then
26848 if (SubM.FAccelerator.Key <> 0) or (SubM.FAccelerator.fVirt <> 0) then
26849 begin
26850 AccTab[ N ].fVirt := SubM.FAccelerator.fVirt;
26851 AccTab[ N ].key := SubM.FAccelerator.Key;
26852 AccTab[ N ].cmd := WORD( SubM.FId );
26853 Inc( N );
26854 if N > MaxAccel then break;
26855 end;
26856 end;
26857 end;
26858 if N > MaxAccel then break;
26859 M := M.fNextMenu;
26860 end;
26861 if N > 0 then
26862 begin
26863 C.fAccelTable := CreateAcceleratorTable( AccTab[ 0 ], N );
26864 C := C.ParentForm;
26865 if C <> nil then
26866 C.SupportMnemonics;
26867 end;
26868 FreeMem( AccTab );
26869 end;
26871 {$ELSE NEW_MENU_ACCELL}
26873 procedure TMenu.SetAccelerator(const Value: TMenuAccelerator);
26875 C: PControl;
26876 M: PMenu;
26877 begin
26878 if (FAccelerator.fVirt = Value.fVirt) and (FAccelerator.Key = Value.Key) then Exit;
26879 FAccelerator := Value;
26880 C := FControl;
26881 M := @Self;
26882 while (C = nil) and (M <> nil) do begin
26883 M := M.Parent;
26884 if (M <> nil) then
26885 C := M.FControl;
26886 end;
26887 if (C <> nil) then
26888 C.SupportMnemonics;
26889 end;
26891 {$ENDIF NEW_MENU_ACCELL}
26893 //[procedure TMenu.SetMenuItemCaption]
26894 procedure TMenu.SetMenuItemCaption( const Value: String );
26895 var MII: TMenuItemInfo;
26896 begin
26897 FCaption := Value;
26898 {AK}if not (WinVer in [wv95,wvNT]) then
26899 {AK} MII.fMask := $40 {MIIM_STRING}
26900 {AK}else begin
26901 MII.fMask := MIIM_TYPE;
26902 MII.fType := MFT_STRING;
26903 {AK}end;
26904 //+++++++++++++++++++ to fix turning radio mark to check mark in NT4
26905 MII.cch := 0;
26906 GetInfo( MII );
26907 //------------------------------------------------------------------
26908 MII.dwTypeData := PChar( Value );
26909 MII.cch := Length( Value );
26910 SetInfo( MII );
26911 end;
26913 //[procedure TMenu.SetMenuBreak]
26914 procedure TMenu.SetMenuBreak( Value: TMenuBreak );
26915 var MII: TMenuItemInfo;
26916 begin
26917 if FId = 0 then Exit;
26918 if FMenuBreak = Value then Exit;
26919 FMenuBreak := Value;
26920 FillChar( MII, Sizeof( MII ), 0 );
26921 MII.fMask := MIIM_TYPE;
26922 MII.dwTypeData := nil;
26923 if GetInfo( MII ) then
26924 begin
26925 MII.fType := MII.fType and not( MFT_MENUBREAK or MFT_MENUBARBREAK ) or
26926 Breaks[ Value ];
26927 SetTypeInfo( MII );
26928 end;
26929 end;
26931 //[procedure TMenu.SetVisible]
26932 procedure TMenu.SetVisible( Value: Boolean );
26933 var I, J: Integer;
26934 M: PMenu;
26935 Before: Integer;
26936 ByPosition: Boolean;
26937 MII: TMenuItemInfo;
26938 begin
26939 if Value then
26940 if FParent <> nil then
26941 FParent.Visible := TRUE;
26942 if Value = FVisible then Exit;
26943 FVisible := Value;
26944 if (FControl <> nil) and (FControl.fMenuObj = @ Self) then
26945 begin
26946 FControl.GetWindowHandle;
26947 if Value then
26948 SetMenu( FControl.fHandle, FHandle )
26949 else
26950 SetMenu( FControl.fHandle, 0 );
26951 Exit;
26952 end;
26953 if FId = 0 then Exit;
26954 if FParent = nil then Exit;
26955 if Value then
26956 begin // show menu item inserting it again into appropriate position
26957 Before := -1;
26958 ByPosition := TRUE;
26959 I := FParent.FItems.IndexOf( @ Self );
26960 for J := I + 1 to FParent.FItems.FCount-1 do
26961 begin
26962 M := FParent.FItems.Items[ J ];
26963 if M.FVisible then
26964 begin
26965 Before := M.FId;
26966 ByPosition := FALSE;
26967 break;
26968 end;
26969 end;
26971 FillChar( MII, Sizeof( MII ), 0 );
26972 MII.cbSize := MenuStructSize;
26973 MII.fMask := MIIM_CHECKMARKS or MIIM_ID or MIIM_STATE or
26974 MIIM_TYPE;
26975 MII.fType := Breaks[ FMenuBreak ];
26976 MII.fState := FSavedState;
26977 MII.wID := FId;
26978 MII.dwItemData := DWORD( FData );
26980 if not FIsSeparator then
26981 begin
26982 MII.fType := MII.fType or MFT_STRING;
26983 MII.dwTypeData := PChar( FCaption );
26984 MII.cch := Length( FCaption );
26986 else
26987 MII.fType := MII.fType or MFT_SEPARATOR;
26989 if FRadioGroup <> 0 then
26990 MII.fType := MII.fType or MFT_RADIOCHECK;
26992 if FOwnerDraw then
26993 MII.fType := MII.fType or MFT_OWNERDRAW;
26995 if FBitmap <> 0 then
26996 begin
26997 MII.fMask := MII.fMask or MIIM_CHECKMARKS;
26998 MII.hbmpUnchecked := FBitmap;
26999 end;
27001 if FHandle <> 0 then
27002 begin
27003 MII.fMask := MII.fMask or MIIM_SUBMENU;
27004 MII.hSubMenu := FHandle;
27005 end;
27007 InsertMenuItem( FParent.FHandle, Before, ByPosition,
27008 Windows.PMenuitemInfo( @ MII )^ );
27010 else
27011 begin // hide menu item removing it
27012 GetState( 0 ); // store menu item state in FSavedState to allow
27013 // changing its state while it is not attached to
27014 // a menu
27015 RemoveMenu( TopParent.FHandle, FId, MF_BYCOMMAND );
27016 end;
27017 if (FControl <> nil) or (FParent <> nil) and (FParent.FControl <> nil) then
27018 RedrawFormMenuBar;
27019 end;
27021 //[procedure TMenu.RadioCheckItem]
27022 procedure TMenu.RadioCheckItem;
27023 var I, J: Integer;
27024 M, First, Last: PMenu;
27025 begin
27026 if (FParent <> nil) and (FRadioGroup <> 0) then
27027 begin
27028 I := FParent.FItems.IndexOf( @ Self );
27029 if I >= 0 then
27030 begin
27031 First := @ Self;
27032 Last := @ Self;
27033 for J := I-1 downto 0 do
27034 begin
27035 M := FParent.FItems.Items[ J ];
27036 if M.FRadioGroup <> FRadioGroup then break;
27037 if M.FVisible then
27038 First := M;
27039 end;
27040 for J := I+1 to FParent.FItems.FCount-1 do
27041 begin
27042 M := FParent.FItems.Items[ J ];
27043 if M.FRadioGroup <> FRadioGroup then break;
27044 if M.FVisible then
27045 Last := M;
27046 end;
27047 if First <> Last then
27048 begin
27049 CheckMenuRadioItem( FParent.FHandle, First.FId, Last.FId,
27050 FId, MF_BYCOMMAND {or MF_CHECKED} );
27051 Exit;
27052 end;
27053 end;
27054 end;
27055 Checked := TRUE;
27056 end;
27058 //[function TMenu.FillMenuItems]
27059 function TMenu.FillMenuItems(AHandle: HMenu; StartIdx: Integer;
27060 const Template: array of PChar): Integer;
27061 var S, S1: PChar;
27062 I: Integer;
27063 MII: TMenuItemInfo;
27064 Item, PrevItem: PMenu;
27065 begin
27066 PrevItem := nil;
27067 I := StartIdx;
27068 while I <= High( Template ) do
27069 begin
27070 S := Template[ I ];
27071 if (S = nil) or (S^ = #0) then break;
27072 if S = {$IFDEF F_P}'' +{$ENDIF} ')' then
27073 begin
27074 Result := I + 1;
27075 Exit;
27076 end;
27079 new( Item, Create );
27080 {+}{++}(*Item := PMenu.Create;*){--}
27081 Item.FVisible := TRUE;
27082 Item.FParent := @ Self;
27083 Item.FItems := NewList;
27084 FItems.Add( Item );
27086 FillChar( MII, Sizeof( MII ), 0 );
27087 MII.cbSize := MenuStructSize;
27088 MII.fMask := MIIM_DATA or MIIM_ID or MIIM_STATE or MIIM_SUBMENU or MIIM_TYPE;
27089 if S <> {$IFDEF F_P}'' +{$ENDIF} '-' then
27090 begin
27091 if (S^ = {$IFDEF F_P}'' +{$ENDIF} '-') or
27092 (S^ = {$IFDEF F_P}'' +{$ENDIF} '+') then
27093 begin
27094 Item.FIsCheckItem := TRUE;
27095 MII.dwItemData := MIDATA_CHECKITEM;
27096 if S^ <> {$IFDEF F_P}'' +{$ENDIF} '-' then
27097 MII.fState := MII.fState or MFS_CHECKED;
27098 Inc( S );
27099 if S^ = {$IFDEF F_P}'' +{$ENDIF} '!' then
27100 begin
27101 MII.fType := MII.fType or MFT_RADIOCHECK;
27102 MII.dwItemData := MII.dwItemData or MIDATA_RADIOITEM;
27103 Inc( S );
27104 if PrevItem <> nil then
27105 begin
27106 if PrevItem.FRadioGroup <> 0 then
27107 Item.FRadioGroup := PrevItem.FRadioGroup;
27108 end;
27109 if Item.FRadioGroup = 0 then
27110 Inc( Item.FRadioGroup );
27111 if S^ = {$IFDEF F_P}'' +{$ENDIF} '!' then
27112 begin
27113 Inc( S );
27114 Inc( Item.FRadioGroup );
27115 end;
27116 end;
27117 end;
27118 Item.FCaption := S;
27120 else
27121 begin
27122 Item.FIsSeparator := TRUE;
27123 MII.fType := MFT_SEPARATOR;
27124 MII.fState := MFS_GRAYED;
27125 MII.wID := 0;
27126 end;
27127 Item.FId := FDynamicMenuID;
27128 Inc( FDynamicMenuID );
27129 MII.wID := Item.FId;
27130 if I <> High( Template ) then //YS
27131 begin //YS
27132 S1 := Template[ I + 1 ];
27133 if S1 = {$IFDEF F_P}'' +{$ENDIF} '(' then Item.FHandle := CreatePopupMenu;
27134 end; //YS
27135 MII.hSubMenu := Item.FHandle;
27136 MII.dwTypeData := PChar( S );
27137 MII.cch := StrLen( S );
27138 InsertMenuItem( AHandle, DWORD(-1), True, Windows.PMenuitemInfo( @ MII )^ );
27139 if Item.FHandle <> 0 then
27140 I := Item.FillMenuItems( Item.FHandle, I + 2, Template )
27141 else
27142 Inc( I );
27143 PrevItem := Item;
27144 end;
27145 Result := I;
27146 end;
27148 //[procedure TMenu.AssignEvents]
27149 procedure TMenu.AssignEvents(StartIdx: Integer;
27150 Events: array of TOnMenuItem);
27151 var I: Integer;
27152 M: PMenu;
27153 begin
27154 for I := 0 to High(Events) do
27155 begin
27156 M := Items[ StartIdx ];
27157 if M = nil then break;
27158 M.FOnMenuItem := Events[ I ];
27159 Inc( StartIdx );
27160 end;
27161 end;
27163 //[procedure TMenu.Popup]
27164 procedure TMenu.Popup(X, Y: Integer);
27165 begin
27166 if Assigned( fOnPopup ) then fOnPopup( @Self );
27167 if not FNotPopup then
27168 TrackPopupMenu( FHandle, FPopupFlags,
27169 X, Y, 0, FControl.Handle, nil );
27170 end;
27172 //[procedure TMenu.PopupEx]
27173 procedure TMenu.PopupEx( X, Y: Integer );
27174 var OldBounds: TRect;
27175 WasVisible: Boolean;
27176 begin
27177 WasVisible := TRUE;
27178 if FControl <> nil then
27179 begin
27180 OldBounds := FControl.BoundsRect;
27181 if not FControl.fIsControl then
27182 begin
27183 WasVisible := FControl.Visible;
27184 if not WasVisible then
27185 FControl.Top := ScreenHeight + 50;
27186 FControl.Show;
27187 end;
27188 end;
27190 // -- by Martin Larsen: -----------------------\
27191 FControl.ProcessMessage; // specific for Win9x |
27192 //---------------------------------------------/
27194 Popup( X, Y );
27195 if FControl <> nil then
27196 begin
27197 if FControl.Top = ScreenHeight + 50 then
27198 begin
27199 if not WasVisible then
27200 FControl.Visible := FALSE;
27201 FControl.BoundsRect := OldBounds;
27202 end;
27203 end;
27204 end;
27206 //[function TMenu.GetItemChecked]
27207 function TMenu.GetItemChecked( Item : Integer ) : Boolean;
27208 begin
27209 Result := Items[ Item ].Checked;
27210 end;
27212 //[procedure TMenu.SetItemChecked]
27213 procedure TMenu.SetItemChecked( Item : Integer; Value : Boolean );
27214 begin
27215 Items[ Item ].Checked := Value;
27216 end;
27218 //[function TMenu.GetMenuItemHandle]
27219 function TMenu.GetMenuItemHandle( Idx : Integer ): DWORD;
27220 begin
27221 Result := Items[ Idx ].FId;
27222 end;
27224 //[procedure TMenu.RadioCheck]
27225 procedure TMenu.RadioCheck( Idx : Integer );
27226 begin
27227 Items[ Idx ].RadioCheckItem;
27228 end;
27230 //[function TMenu.GetItemBitmap]
27231 function TMenu.GetItemBitmap(Idx: Integer): HBitmap;
27232 begin
27233 Result := Items[ Idx ].Bitmap;
27234 end;
27236 //[procedure TMenu.SetItemBitmap]
27237 procedure TMenu.SetItemBitmap(Idx: Integer; const Value: HBitmap);
27238 begin
27239 Items[ Idx ].Bitmap := Value;
27240 end;
27242 //[procedure TMenu.AssignBitmaps]
27243 procedure TMenu.AssignBitmaps(StartIdx: Integer; Bitmaps: array of HBitmap);
27244 var I: Integer;
27245 begin
27246 for I := 0 to High(Bitmaps) do
27247 ItemBitmap[ I + StartIdx ] := Bitmaps[ I ];
27248 end;
27250 //[function TMenu.GetItemText]
27251 function TMenu.GetItemText(Idx: Integer): String;
27252 begin
27253 Result := Items[ Idx ].FCaption;
27254 end;
27256 //[procedure TMenu.SetItemText]
27257 procedure TMenu.SetItemText(Idx: Integer; const Value: String);
27258 begin
27259 Items[ Idx ].Caption := Value;
27260 end;
27262 //[function TMenu.GetItemEnabled]
27263 function TMenu.GetItemEnabled(Idx: Integer): Boolean;
27264 begin
27265 Result := Items[ Idx ].Enabled;
27266 end;
27268 //[procedure TMenu.SetItemEnabled]
27269 procedure TMenu.SetItemEnabled(Idx: Integer; const Value: Boolean);
27270 begin
27271 Items[ Idx ].Enabled := Value;
27272 end;
27274 //[function TMenu.GetItemVisible]
27275 function TMenu.GetItemVisible(Idx: Integer): Boolean;
27276 begin
27277 Result := Items[ Idx ].Visible;
27278 end;
27280 //[procedure TMenu.SetItemVisible]
27281 procedure TMenu.SetItemVisible(Idx: Integer; const Value: Boolean);
27282 begin
27283 Items[ Idx ].Visible := Value;
27284 end;
27286 //[function TMenu.ParentItem]
27287 function TMenu.ParentItem( Idx: Integer ): Integer;
27288 begin
27289 Result := TopParent.IndexOf( Items[ Idx ].FParent );
27290 end;
27292 //[function TMenu.GetItemAccelerator]
27293 function TMenu.GetItemAccelerator(Idx: Integer): TMenuAccelerator;
27294 begin
27295 Result := Items[ Idx ].Accelerator;
27296 end;
27298 //[procedure TMenu.SetItemAccelerator]
27299 procedure TMenu.SetItemAccelerator(Idx: Integer; const Value: TMenuAccelerator);
27300 begin
27301 Items[ Idx ].Accelerator := Value;
27302 end;
27304 //[function TMenu.GetItemSubMenu]
27305 function TMenu.GetItemSubMenu( Idx: Integer ): HMenu;
27306 begin
27307 Result := Items[ Idx ].SubMenu;
27308 end;
27310 //[function WndProcHelp FORWARD DECLARATION]
27311 function WndProcHelp( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
27312 forward;
27314 //[procedure TMenu.SetHelpContext]
27315 procedure TMenu.SetHelpContext( Value: Integer );
27316 var Form, C: PControl;
27317 begin
27318 if TopParent <> @ Self then Exit;
27319 // Help context can not be associated with individual menu items
27320 FHelpContext := Value;
27321 C := FControl;
27322 if C = nil then Exit;
27323 Form := C.ParentForm;
27324 Form.AttachProc( WndProcHelp );
27325 SetMenuContextHelpID( FHandle, Value );
27326 end;
27328 //[procedure TMenu.SetSubmenu]
27329 procedure TMenu.SetSubmenu( Value: HMenu );
27330 var MII: TMenuItemInfo;
27331 begin
27332 MII.fMask := MIIM_SUBMENU;
27333 MII.hSubMenu := Value;
27334 SetInfo( MII );
27335 FHandle := Value;
27336 end;
27338 //[function WndProcMeasureItem]
27339 function WndProcMeasureItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
27340 var MIS: PMeasureItemStruct;
27341 M, SM: PMenu;
27342 H, I: Integer;
27343 begin
27344 Result := FALSE;
27345 if (Msg.message = WM_MEASUREITEM) and (Msg.wParam = 0) then
27346 begin
27347 MIS := Pointer( Msg.lParam );
27348 if MIS.CtlType = ODT_MENU then
27349 begin
27350 M := Pointer( Sender.fMenuObj );
27351 while M <> nil do
27352 begin
27353 SM := M.Items[ MIS.itemID ];
27354 if SM <> nil then
27355 begin
27356 Sender.CallDefWndProc( Msg );
27357 I := M.IndexOf( SM );
27358 if Assigned( SM.OnMeasureItem ) then
27359 M := SM;
27360 if not Assigned( M.OnMeasureItem ) then
27361 Exit;
27362 H := M.OnMeasureItem( M, I );
27363 if HiWord( H ) <> 0 then
27364 MIS.itemWidth := HiWord( H );
27365 if LoWord( H ) <> 0 then
27366 MIS.itemHeight := LoWord( H );
27367 Rslt := 1;
27368 Result := TRUE;
27369 break;
27370 end;
27371 M := M.fNextMenu;
27372 end;
27373 end;
27374 end;
27375 end;
27377 //[procedure TMenu.SetOnMeasureItem]
27378 procedure TMenu.SetOnMeasureItem( const Value: TOnMeasureItem );
27379 var C: PControl;
27380 begin
27381 FOnMeasureItem := Value;
27382 C := TopParent.FControl;
27383 if C <> nil then
27384 C.AttachProc( WndProcMeasureItem );
27385 end;
27387 //[function WndProcDrawItem]
27388 function WndProcDrawItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
27389 type PDrawAction = ^TDrawAction;
27390 PDrawState = ^TDrawState;
27391 var DIS: PDrawItemStruct;
27392 M, SM: PMenu;
27393 I: Integer;
27394 begin
27395 Result := FALSE;
27396 if (Msg.message = WM_DRAWITEM) and (Msg.wParam = 0) then
27397 begin
27398 DIS := Pointer( Msg.lParam );
27399 if DIS.CtlType = ODT_MENU then
27400 begin
27401 M := Pointer( Sender.fMenuObj );
27402 while M <> nil do
27403 begin
27404 SM := M.Items[ DIS.itemID ];
27405 if SM <> nil then
27406 begin
27407 I := M.IndexOf( SM );
27408 if Assigned( SM.OnDrawItem ) then
27409 M := SM;
27410 if Assigned( M.OnDrawItem ) then
27411 begin
27412 if not M.OnDrawItem( M, DIS.hDC, DIS.rcItem, I,
27413 PDrawAction( @ DIS.itemAction )^,
27414 PDrawState( @ DIS.itemState )^ ) then Exit;
27416 else Exit;
27417 Rslt := 1;
27418 Result := TRUE;
27419 break;
27420 end;
27421 M := M.fNextMenu;
27422 end;
27423 end;
27424 end;
27425 end;
27427 //[procedure TMenu.SetOnDrawItem]
27428 procedure TMenu.SetOnDrawItem( const Value: TOnDrawItem );
27429 var C: PControl;
27430 begin
27431 FOnDrawItem := Value;
27432 C := TopParent.FControl;
27433 if C <> nil then
27434 C.AttachProc( WndProcDrawItem );
27435 end;
27437 //[procedure TMenu.SetOwnerDraw]
27438 procedure TMenu.SetOwnerDraw( Value: Boolean );
27439 const Masks: array[ Boolean ] of DWORD = ( 0, $FFFFFFFF );
27440 var MII: TMenuItemInfo;
27441 begin
27442 FOwnerDraw := Value;
27443 FillChar( MII, Sizeof( MII ), 0 );
27444 MII.fMask := MIIM_TYPE;
27445 MII.dwTypeData := nil;
27446 if GetInfo( MII ) then
27447 begin
27448 MII.fType := MII.fType and not MFT_OWNERDRAW or
27449 (MFT_OWNERDRAW and Masks[ Value ]);
27450 SetTypeInfo( MII );
27451 end;
27452 end;
27454 //[function TMenu.Insert]
27455 function TMenu.Insert(InsertBefore: Integer; ACaption: PChar; Event: TOnMenuItem;
27456 Options: TMenuOptions): PMenu;
27457 const
27458 MenuStateFlags: array[TMenuOption] of Integer = (MFS_DEFAULT, MFS_DISABLED, MFS_CHECKED, 0, 0,
27459 MFS_DISABLED, 0, 0, 0, 0);
27460 MenuTypeFlags: array[TMenuOption] of Integer = (0, 0, 0, 0, MFT_RADIOCHECK, MFT_SEPARATOR, MFT_BITMAP, 0,
27461 MFT_MENUBREAK, MFT_MENUBARBREAK);
27462 var M: PMenu;
27463 MII: TMenuItemInfo;
27464 begin
27466 new( Result, Create );
27467 {+}{++}(*Result := PMenu.Create;*){--}
27468 Result.FVisible := TRUE;
27469 Result.FParent := @ Self;
27470 Result.FItems := NewList;
27471 Result.FIsSeparator := moSeparator in Options;
27472 if FHandle = 0 then
27473 SetSubMenu( CreatePopupMenu );
27474 M := nil;
27475 if (InsertBefore >= 0) and (InsertBefore < 4096) then
27476 begin
27477 M := Items[ InsertBefore ];
27478 if M <> nil then
27479 begin
27480 InsertBefore := M.FId;
27481 M.Parent.FItems.Insert( M.Parent.FItems.IndexOf( M ), Result );
27482 end;
27483 end;
27484 if M = nil then
27485 begin
27486 InsertBefore := -1;
27487 FItems.Add( Result );
27488 end;
27489 Result.FOnMenuItem := Event;
27491 FillChar( MII, Sizeof( MII ), 0 );
27492 MII.cbSize := MenuStructSize;
27493 MII.fMask := MIIM_DATA or MIIM_ID or MIIM_STATE or MIIM_SUBMENU or MIIM_TYPE;
27495 MII.fState := MakeFlags( Pointer( @Options ), MenuStateFlags);
27496 MII.fType := MakeFlags( Pointer( @Options ), MenuTypeFlags);
27497 Result.FId := FDynamicMenuID;
27498 Inc( FDynamicMenuID );
27499 MII.wID := Result.FId;
27500 if moSubMenu in Options
27501 then begin
27502 Result.FHandle := CreatePopupMenu;
27503 MII.hSubMenu := Result.FHandle;
27504 end;
27505 MII.dwTypeData := ACaption;
27506 if not (moBitmap in Options) then MII.cch := StrLen( ACaption );
27507 InsertMenuItem( FHandle, InsertBefore, InsertBefore = -1,
27508 Windows.PMenuItemInfo( @ MII )^ );
27509 if moBitmap in Options then
27510 begin
27511 Result.BitmapItem := DWORD( ACaption );
27513 else
27514 Result.FCaption := ACaption;
27515 RedrawFormMenuBar;
27516 end;
27518 //[function TMenu.AddItem]
27519 function TMenu.AddItem(ACaption: PChar; Event: TOnMenuItem; Options: TMenuOptions): Integer;
27520 begin
27521 Result := InsertItem( -1, ACaption, Event, Options );
27522 end;
27524 //[function TMenu.InsertItem]
27525 function TMenu.InsertItem( InsertBefore: Integer; ACaption: PChar; Event: TOnMenuItem;
27526 Options: TMenuOptions): Integer;
27527 begin
27528 Result := InsertItemEx( InsertBefore, ACaption, Event, Options, FALSE );
27529 end;
27531 //[function TMenu.InsertItemEx]
27532 function TMenu.InsertItemEx(InsertBefore: Integer; ACaption: PChar;
27533 Event: TOnMenuItem; Options: TMenuOptions; ByPosition: Boolean): Integer;
27534 var M: PMenu;
27535 begin
27536 M := Insert( InsertBefore, ACaption, Event, Options );
27537 Result := M.FId;
27538 end;
27540 //[procedure TMenu.InsertSubMenu]
27541 procedure TMenu.InsertSubMenu( SubMenuToInsert: PMenu; InsertBefore: Integer );
27542 var AFlags: DWORD;
27543 M: PMenu;
27544 MII: TMenuItemInfo;
27545 begin
27546 if SubMenuToInsert.FParent <> nil then
27547 SubMenuToInsert := SubMenuToInsert.FParent.RemoveSubMenu( SubMenuToInsert.FId );
27548 if SubMenuToInsert = nil then Exit;
27550 AFlags := MF_BYPOSITION;
27551 M := nil;
27552 if (InsertBefore >= 0) and (InsertBefore < 4096) then
27553 begin
27554 M := Items[ InsertBefore ];
27555 if M = nil then
27556 InsertBefore := -1
27557 else
27558 InsertBefore := M.FId;
27559 end;
27560 if M = nil then
27561 begin
27562 FItems.Add( SubMenuToInsert );
27563 SubMenuToInsert.FParent := @ Self;
27565 else
27566 begin
27567 M.FParent.FItems.Insert( M.FParent.FItems.IndexOf( M ), SubMenuToInsert );
27568 SubMenuToInsert.FParent := M.FParent;
27569 end;
27571 if InsertBefore > 0 then
27572 AFlags := MF_BYCOMMAND;
27573 if SubMenuToInsert.FBmpItem <> 0 then
27574 InsertMenu( FHandle, InsertBefore, AFlags or MF_BITMAP or MF_POPUP, SubMenuToInsert.FHandle,
27575 PChar( SubMenuToInsert.FBmpItem ) )
27576 else
27577 InsertMenu( FHandle, InsertBefore, AFlags or MF_STRING or MF_POPUP, SubMenuToInsert.FHandle,
27578 PChar( SubMenuToInsert.Caption ) );
27579 if SubMenuToInsert.FId = 0 then
27580 begin
27581 SubMenuToInsert.FId := FDynamicMenuID;
27582 Inc( FDynamicMenuID );
27583 MII.cbSize := MenuStructSize;
27584 MII.fMask := MIIM_ID;
27585 MII.wID := SubMenuToInsert.FId;
27586 SetMenuItemInfo( SubMenuToInsert.FParent.FHandle, SubMenuToInsert.FParent.FItems.IndexOf( SubMenuToInsert ),
27587 TRUE, Windows.PMenuItemInfo( @ MII )^ );
27588 end;
27589 RedrawFormMenuBar;
27590 end;
27592 //[function TMenu.RemoveSubMenu]
27593 function TMenu.RemoveSubMenu( ItemToRemove: Integer ): PMenu;
27594 {$IFDEF DEBUG_MENU}var OK: Boolean; {$ENDIF}
27595 begin
27596 Result := Items[ ItemToRemove ];
27597 if Result = nil then Exit;
27598 if Result.FParent <> nil then
27599 {$IFDEF DEBUG_MENU} OK := {$ENDIF}
27600 RemoveMenu( Result.FParent.FHandle, Result.FId, MF_BYCOMMAND )
27601 else
27602 {$IFDEF DEBUG_MENU} OK := {$ENDIF}
27603 RemoveMenu( FHandle, Result.FId, MF_BYCOMMAND );
27604 {$IFDEF DEBUG_MENU}
27605 if not OK then
27606 ShowMessage( 'Error removing menu: ' + Int2Str( GetLastError ) + ' - ' +
27607 SysErrorMessage( GetLastError ) );
27608 {$ENDIF}
27609 if Count = 0 then
27610 begin
27611 Result.Free;
27612 Result := nil;
27613 end;
27614 RedrawFormMenuBar;
27615 end;
27617 //[procedure ClearText]
27618 procedure ClearText( Sender: PControl );
27619 begin
27620 Sender.Caption := '';
27621 end;
27623 //[procedure ClearListbox]
27624 procedure ClearListbox( Sender: PControl );
27625 begin
27626 Sender.Perform( LB_RESETCONTENT, 0, 0 );
27627 end;
27629 //[procedure ClearCombobox]
27630 procedure ClearCombobox( Sender: PControl );
27631 begin
27632 Sender.Perform( CB_RESETCONTENT, 0, 0 );
27633 end;
27635 //[procedure ClearListView]
27636 procedure ClearListView( Sender: PControl );
27637 begin
27638 Sender.Perform( LVM_DELETEALLITEMS, 0, 0 );
27639 end;
27641 //[procedure ClearToolbar]
27642 procedure ClearToolbar( Sender: PControl );
27643 begin
27644 while Sender.TBButtonCount > 0 do
27645 Sender.TBDeleteButton( Sender.TBIndex2Item( 0 ) );
27646 Sender.Perform( TB_SETBITMAPSIZE, 0, 0 );
27647 end;
27649 { -- Constructor of canvas -- }
27650 //[function NewCanvas]
27651 function NewCanvas( DC: HDC ): PCanvas;
27652 begin
27654 New( Result, Create );
27656 {++}(*
27657 Result := PCanvas.Create;
27658 *){--}
27659 Result.ModeCopy := cmSrcCopy;
27660 if DC <> 0 then
27661 begin
27662 Result.SetHandle( DC );
27663 //Result.fIsPaintDC := True; // If Canvas will be destroyed, DC will not be deleted
27664 end;
27665 end;
27666 //[END NewCanvas]
27668 { -- Contructors of controls -- }
27670 {$IFDEF ASM_VERSION}
27671 //[FUNCTION _NewTControl]
27672 function _NewTControl( AParent: PControl ): PControl;
27673 begin
27674 New( Result, CreateParented( AParent ) );
27675 end;
27676 //[END _NewTControl]
27678 //[function _NewWindowed]
27679 function _NewWindowed( AParent: PControl; ControlClassName: PChar; Ctl3D: Boolean ): PControl;
27681 PUSH EBX
27682 PUSH ESI
27683 PUSH EDI
27685 PUSH ECX // Ctl3D
27686 PUSH EDX // ControlClassName
27688 MOV ESI, EAX // ESI = AParent
27689 CALL _NewTControl
27690 XCHG EBX, EAX // EBX = Result
27691 POP [EBX].TControl.fControlClassName
27692 INC [EBX].TControl.fWindowed
27694 INC EAX
27695 POP EDX // DL = parameter Ctl3D
27696 TEST ESI, ESI
27697 JZ @@no_parent
27699 LEA ESI, [ESI].TControl.fWndProcResizeFlicks
27700 LEA EDI, [EBX].TControl.fWndProcResizeFlicks
27701 MOVSD // fWndProcResizeFlicks
27702 MOVSD // fGotoControl
27703 //MOVSW // fDoubleBuffered, fTransparent
27704 LODSB // fCtl3Dchild
27705 STOSB
27706 DEC AL
27707 LODSB // fCtl3D
27708 JZ @@passed3D
27709 XOR EDX, EDX
27710 @@passed3D:
27711 XCHG EAX, EDX
27712 STOSB // fCtl3D
27714 MOVSD // fTextColor
27715 LODSD
27716 XCHG EDX, EAX
27717 XOR EAX, EAX
27718 PUSH EDX
27719 CALL TGraphicTool.Assign
27720 STOSD // fFont
27721 POP EDX
27722 XCHG ECX, EAX
27723 JECXZ @@no_font
27724 MOV [ECX].TGraphicTool.fParentGDITool, EDX
27725 MOV [ECX].TGraphicTool.fOnChange.TMethod.Code, offset[TControl.FontChanged]
27726 MOV [ECX].TGraphicTool.fOnChange.TMethod.Data, EBX
27727 MOV EAX, EBX
27728 MOV EDX, ECX
27729 CALL TControl.FontChanged
27730 @@no_font:
27732 MOVSD // fColor
27733 LODSD
27734 XCHG EDX, EAX
27735 XOR EAX, EAX
27736 PUSH EDX
27737 CALL TGraphicTool.Assign
27738 STOSD // fBrush
27739 POP EDX
27740 XCHG ECX, EAX
27741 JECXZ @@no_brush
27742 MOV [ECX].TGraphicTool.fParentGDITool, EDX
27743 MOV [ECX].TGraphicTool.fOnChange.TMethod.Code, offset[TControl.BrushChanged]
27744 MOV [ECX].TGraphicTool.fOnChange.TMethod.Data, EBX
27745 MOV EAX, EBX
27746 MOV EDX, ECX
27747 CALL TControl.BrushChanged
27748 @@no_brush:
27750 LODSD
27751 STOSD // fMargin
27752 STOSD // fBoundsRect.Left
27753 PUSH EAX
27754 ADD EAX, [ESI+16] // AParent.fClientTop
27755 STOSD // fBoundsRect.Top
27756 POP EAX
27757 ADD EAX, 64
27758 STOSD // fBoundsRect.Right
27759 STOSD // fBoundsRect.Bottom
27761 @@no_parent:
27762 XCHG EAX, EBX
27763 //DEC byte ptr [EAX].TControl.fAlphaBlend
27764 //INC byte ptr [EAX].TControl.fEraseUpdRgn
27765 POP EDI
27766 POP ESI
27767 POP EBX
27768 end;
27769 {$ELSE ASM_VERSION} //Pascal
27770 function _NewWindowed( AParent: PControl; ControlClassName: PChar; Ctl3D: Boolean ): PControl;
27771 begin
27773 New( Result, CreateParented( AParent ) );
27774 {+}{++}(*Result := PControl.CreateParented( AParent );*){--}
27775 Result.fControlClassName := ControlClassName;
27776 if AParent <> nil then
27777 begin
27778 Result.fWndProcResizeFlicks := AParent.fWndProcResizeFlicks;
27779 Result.fGotoControl := AParent.fGotoControl;
27780 //Result.fDoubleBuffered := AParent.fDoubleBuffered;
27781 //Result.fTransparent := AParent.fTransparent;
27782 Result.fCtl3Dchild := AParent.fCtl3Dchild;
27783 if AParent.fCtl3Dchild then
27784 Result.fCtl3D := Ctl3D
27785 else
27786 Result.fCtl3D := False;
27787 Result.fMargin := AParent.fMargin;
27788 with Result.fBoundsRect do
27789 begin
27790 Left := AParent.fMargin + AParent.fClientLeft;
27791 Top := AParent.fMargin + AParent.fClientTop;
27792 Right := Left + 64;
27793 Bottom := Top + 64;
27794 end;
27795 Result.fTextColor := AParent.fTextColor;
27796 Result.fFont := Result.fFont.Assign( AParent.fFont );
27797 if Result.fFont <> nil then
27798 begin
27799 Result.fFont.fParentGDITool := AParent.fFont;
27800 Result.fFont.fOnChange := Result.FontChanged;
27801 Result.FontChanged( Result.fFont );
27802 end;
27803 Result.fColor := AParent.fColor;
27804 Result.fBrush := Result.fBrush.Assign( AParent.fBrush );
27805 if Result.fBrush <> nil then
27806 begin
27807 Result.fBrush.fParentGDITool := AParent.fBrush;
27808 Result.fBrush.fOnChange := Result.BrushChanged;
27809 Result.BrushChanged( Result.fBrush );
27810 end;
27811 end;
27812 //Result.fAlphaBlend := 255;
27813 //Result.fEraseUpdRgn := TRUE;
27814 end;
27815 //[END _NewWindowed]
27816 {$ENDIF ASM_VERSION}
27818 //===================== Form ========================//
27820 {$IFDEF USE_CONSTRUCTORS}
27821 //[function NewForm]
27822 function NewForm( AParent: PControl; const Caption: String ): PControl;
27823 begin
27824 new( Result, CreateForm( AParent, Caption ) );
27825 end;
27826 //[END NewForm]
27827 {$ELSE not_USE_CONSTRUCTORS}
27829 //[FUNCTION NewForm]
27830 {$IFDEF ASM_VERSION}
27831 function NewForm( AParent: PControl; const Caption: String ): PControl;
27832 const FormClass: array[ 0..4 ] of Char = ( 'F', 'o', 'r', 'm', #0 );
27834 PUSH EBX
27835 PUSH EDX
27836 MOV EDX, offset[FormClass]
27837 MOV CL, 1
27838 CALL _NewWindowed
27839 MOV EBX, EAX
27840 INC [EBX].TControl.fSizeGrip
27841 OR byte ptr [EBX].TControl.fClsStyle, CS_DBLCLKS
27842 MOV EDX, offset[WndProcForm]
27843 CALL TControl.AttachProc
27844 MOV EDX, offset[WndProcDoEraseBkgnd]
27845 MOV EAX, EBX
27846 CALL TControl.AttachProc
27847 POP EDX
27848 MOV EAX, EBX
27849 CALL TControl.SetCaption
27850 INC [EBX].TControl.fSizeGrip
27851 INC [EBX].TControl.fIsForm
27852 XCHG EAX, EBX
27853 POP EBX
27854 end;
27855 {$ELSE ASM_VERSION} //Pascal
27856 function NewForm( AParent: PControl; const Caption: String ): PControl;
27857 begin
27858 Result := _NewWindowed( AParent, 'Form', True );
27859 Result.fClsStyle := Result.fClsStyle or CS_DBLCLKS;
27860 Result.AttachProc( WndProcForm );
27861 Result.AttachProc( WndProcDoEraseBkgnd );
27862 Result.Caption := Caption;
27863 Result.fSizeGrip := TRUE;
27864 Result.fIsForm := TRUE;
27865 end;
27866 {$ENDIF ASM_VERSION}
27867 //[END NewForm]
27869 {$ENDIF USE_CONSTRUCTORS}
27871 //===================== Applet button ========================//
27873 //{$DEFINE WNDPROCAPP_USED}
27874 {$IFDEF WNDPROCAPP_USED}
27876 //[FUNCTION WndProcApp]
27877 {$IFDEF ASM_VERSION}
27878 {$IFDEF WNDPROCAPP_ASM_USED}
27879 function WndProcApp(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
27881 CMP word ptr [EDX].TMsg.message, WM_SETFOCUS
27882 JNZ @@chk_CLOSE
27883 MOV ECX, [EAX].TControl.FCurrentControl
27884 JECXZ @@ret_false
27885 XCHG EAX, ECX
27886 PUSH EAX
27887 CALL CallTControlCreateWindow
27888 POP EAX
27889 PUSH [EAX].TControl.fHandle
27890 CALL SetFocus
27891 MOV AL, 1
27893 @@chk_CLOSE:
27894 CMP word ptr [EDX].TMsg.message, WM_SYSCOMMAND
27895 JNZ @@ret_false
27896 MOV EDX, dword ptr [EDX].TMsg.wParam
27897 AND DX, $FFF0
27898 CMP DX, SC_CLOSE
27899 JNZ @@ret_false
27900 PUSH ECX
27901 MOV ECX, [EAX].TControl.fChildren
27902 JECXZ @@ret_false1
27903 XCHG EAX, ECX
27904 MOV ECX, [EAX].TList.fCount
27905 JECXZ @@ret_false1
27906 MOV EAX, [EAX].TList.fItems
27907 MOV ECX, dword ptr [EAX]
27908 JECXZ @@ret_false1
27909 XCHG EAX, ECX
27910 PUSH EAX
27911 CALL TControl.IsMainWindow
27912 TEST EAX, EAX
27913 POP EAX
27914 JZ @@ret_false1
27915 CALL TControl.Close
27916 POP ECX
27917 XOR EAX, EAX
27918 MOV dword ptr [ECX], EAX
27919 INC EAX
27920 JMP @@exit
27921 @@ret_false1:
27922 POP ECX
27923 @@ret_false:
27924 XOR EAX, EAX
27925 @@exit:
27926 end;
27927 {$ENDIF}
27928 {$ELSE ASM_VERSION} //Pascal
27929 function WndProcApp(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
27930 begin
27931 Result := False;
27932 case Msg.message of
27933 WM_SETFOCUS:
27934 {$IFDEF NEW_MODAL}
27935 if Self_.fModalForm <> nil then
27936 SetFocus( Self_.fModalForm.fHandle )
27937 else if ( Self_.FCurrentControl <> nil ) and not
27938 ( Self_.fCurrentControl.IsForm xor Self_.fIsApplet ) then
27939 {$ELSE not_NEW_MODAL}
27940 if Self_.FCurrentControl <> nil then
27941 {$ENDIF NEW_MODAL}
27942 begin
27943 Self_.FCurrentControl.CreateWindow; //virtual!!!
27944 SetFocus( Self_.FCurrentControl.fHandle );
27945 Result := True;
27946 end;
27947 WM_SYSCOMMAND:
27948 if Msg.wParam and $FFF0 = SC_CLOSE then
27949 if (Self_.fChildren <> nil) and (Self_.fChildren.fCount > 0) and
27950 PControl( Self_.fChildren.fItems[ 0 ] ).IsMainWindow then
27951 begin
27952 PControl( Self_.fChildren.fItems[ 0 ] ).Close;
27953 Rslt := 0;
27954 Result := TRUE;
27955 end;
27956 end;
27957 end;
27958 {$ENDIF ASM_VERSION}
27959 //[END WndProcApp]
27961 {$ENDIF WNDPROCAPP_USED}
27963 {$IFDEF USE_CONSTRUCTORS}
27964 {$DEFINE CREATEAPPBUTTON_USED}
27965 //[function NewApplet]
27966 function NewApplet( const Caption: String ): PControl;
27967 begin
27968 new( Result, CreateApplet( Caption ) );
27969 end;
27970 //[END NewApplet]
27971 {$ELSE not_USE_CONSTRUCTORS}
27973 //[FUNCTION NewApplet]
27974 {$IFDEF ASM_VERSION}
27975 function NewApplet( const Caption: String ): PControl;
27976 const AppClass: array[ 0..3 ] of Char = ( 'A', 'p', 'p', #0 );
27978 XOR ECX, ECX
27979 INC ECX
27980 MOV [AppButtonUsed], CL
27981 PUSH EAX
27982 MOV EDX, offset[AppClass]
27983 XOR EAX, EAX
27984 CALL _NewWindowed
27985 INC [EAX].TControl.FIsApplet
27986 MOV word ptr [EAX].TControl.fStyle + 2, $90CA //WS_VISIBLE or WS_SYSMENU or WS_POPUP or WS_MINIMIZEBOX or WS_CAPTION
27987 MOV byte ptr [EAX].TControl.fExStyle + 2, WS_EX_APPWINDOW shr 16 // WS_EX_APPWINDOW = $40000
27988 CALL @@newapp1
27990 // BODY of CreateAppButton here:
27991 PUSH ESI
27992 PUSH 0
27993 PUSH [EAX].TControl.fHandle
27994 CALL GetSystemMenu
27995 MOV ESI, offset[DeleteMenu]
27997 XCHG ECX, EAX
27998 MOV EAX, SC_MAXIMIZE
28001 PUSH EDX
28002 PUSH EAX
28003 PUSH ECX
28005 PUSH EDX
28006 {$IFDEF PARANOIA}
28007 DB $2C, $20
28008 {$ELSE}
28009 SUB AL, $20 // SC_MOVE
28010 {$ENDIF}
28011 PUSH EAX
28012 PUSH ECX
28014 PUSH EDX
28015 {$IFDEF PARANOIA}
28016 DB $2C, $10
28017 {$ELSE}
28018 SUB AL, $10 // SC_SIZE
28019 {$ENDIF}
28020 PUSH EAX
28021 PUSH ECX
28023 PUSH 1 // MF_GRAYED or MF_BYCOMMAND
28024 MOV AX, SC_RESTORE
28025 PUSH EAX
28026 PUSH ECX
28028 CALL EnableMenuItem
28029 CALL ESI
28030 CALL ESI
28031 CALL ESI
28032 POP ESI
28033 @@ret_false:
28034 XOR EAX, EAX
28037 @@chk_CLOSE:
28038 CMP word ptr [EDX].TMsg.message, WM_SYSCOMMAND
28039 JNZ @@ret_false
28040 MOV EDX, dword ptr [EDX].TMsg.wParam
28041 AND DX, $FFF0
28042 CMP DX, SC_CLOSE
28043 JNZ @@ret_false
28044 PUSH ECX
28045 MOV ECX, [EAX].TControl.fChildren
28046 JECXZ @@ret_false1
28047 XCHG EAX, ECX
28048 MOV ECX, [EAX].TList.fCount
28049 JECXZ @@ret_false1
28050 MOV EAX, [EAX].TList.fItems
28051 MOV ECX, dword ptr [EAX]
28052 JECXZ @@ret_false1
28053 XCHG EAX, ECX
28054 PUSH EAX
28055 CALL TControl.IsMainWindow
28056 TEST EAX, EAX
28057 POP EAX
28058 JZ @@ret_false1
28059 CALL TControl.Close
28060 POP ECX
28061 XOR EAX, EAX
28062 MOV dword ptr [ECX], EAX
28063 INC EAX
28065 @@ret_false1:
28066 POP ECX
28067 JMP @@ret_false
28069 @@newapp1:
28070 //MOV [EAX].TControl.FCreateWndExt, offset[CreateAppButton]
28071 POP [EAX].TControl.FCreateWndExt
28072 PUSH EAX
28073 CALL @@newapp2
28075 // BODY of WndProcApp here:
28076 CMP word ptr [EDX].TMsg.message, WM_SETFOCUS
28077 JNZ @@chk_CLOSE
28078 MOV ECX, [EAX].TControl.FCurrentControl
28079 JECXZ @@ret_false
28080 XCHG EAX, ECX
28082 PUSH EAX
28083 CALL CallTControlCreateWindow
28084 POP EAX
28085 PUSH [EAX].TControl.fHandle
28087 CALL SetFocus
28088 MOV AL, 1
28091 @@newapp2:
28092 POP EDX
28093 CALL TControl.AttachProc
28094 POP EAX
28095 POP EDX
28096 PUSH EAX
28097 CALL TControl.SetCaption
28098 POP EAX
28099 end;
28101 {$ELSE ASM_VERSION} //Pascal
28103 //[procedure CreateAppButton]
28104 procedure CreateAppButton( App: PControl );
28105 var M: HMenu;
28106 begin
28107 M := GetSystemMenu( App.fHandle, False );
28108 DeleteMenu( M, SC_MAXIMIZE, MF_BYCOMMAND );
28109 DeleteMenu( M, SC_MOVE, MF_BYCOMMAND );
28110 DeleteMenu( M, SC_SIZE, MF_BYCOMMAND );
28111 EnableMenuItem( M, SC_RESTORE, MF_GRAYED or MF_BYCOMMAND );
28112 end;
28114 //[function NewApplet]
28115 function NewApplet( const Caption: String ): PControl;
28116 begin
28117 AppButtonUsed := True;
28118 Result := _NewWindowed( nil, 'App', True );
28119 Result.FIsApplet := TRUE;
28120 Result.fStyle := WS_VISIBLE or WS_SYSMENU or WS_POPUP or WS_MINIMIZEBOX or WS_CAPTION;
28121 Result.fExStyle := WS_EX_APPWINDOW;
28122 Result.FCreateWndExt := CreateAppButton;
28123 Result.AttachProc( WndProcApp );
28124 Result.Caption := Caption;
28125 end;
28126 {$ENDIF ASM_VERSION}
28127 //[END NewApplet]
28128 {$ENDIF USE_CONSTRUCTORS}
28130 {$IFDEF CREATEAPPBUTTON_USED}
28131 procedure CreateAppButton( App: PControl );
28133 {$IFDEF F_P}
28134 MOV EAX, [App]
28135 {$ENDIF F_P}
28136 PUSH ESI
28137 PUSH 0
28138 PUSH [EAX].TControl.fHandle
28139 CALL GetSystemMenu
28140 MOV ESI, offset[DeleteMenu]
28142 XCHG ECX, EAX
28143 MOV EAX, SC_MAXIMIZE
28146 PUSH EDX
28147 PUSH EAX
28148 PUSH ECX
28150 PUSH EDX
28151 {$IFDEF PARANOIA}
28152 DB $2C, $20
28153 {$ELSE}
28154 SUB AL, $20 // SC_MOVE
28155 {$ENDIF}
28156 PUSH EAX
28157 PUSH ECX
28159 PUSH EDX
28160 {$IFDEF PARANOIA}
28161 DB $2C, $10
28162 {$ELSE}
28163 SUB AL, $10 // SC_SIZE
28164 {$ENDIF}
28165 PUSH EAX
28166 PUSH ECX
28168 PUSH 1 // MF_GRAYED or MF_BYCOMMAND
28169 MOV AX, SC_RESTORE
28170 PUSH EAX
28171 PUSH ECX
28173 CALL EnableMenuItem
28174 CALL ESI
28175 CALL ESI
28176 CALL ESI
28177 POP ESI
28178 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
28179 {$ENDIF CREATEAPPBUTTON_USED}
28181 var CtlIdCount: WORD = $8000;
28184 {$IFNDEF ASM_VERSION}
28185 //{$DEFINE CREATEPARAMS2_USED}
28186 {$ENDIF}
28187 {$IFDEF USE_CONSTRUCTORS}
28188 //{$DEFINE CREATEPARAMS2_USED}
28189 {$ENDIF}
28192 {$IFDEF CREATEPARAMS2_USED} // seems not needed more
28193 //[procedure CreateParams2]
28194 procedure CreateParams2( Self_: PControl; var Params: TCreateParams);
28195 begin
28196 Self_.CreateSubclass( Params, Self_.fControlClassName );
28197 end;
28198 {$ENDIF}
28200 //[FUNCTION _NewControl]
28201 {$IFDEF ASM_VERSION}
28202 function _NewControl( AParent: PControl; ControlClassName: PChar;
28203 Style: DWORD; Ctl3D: Boolean; Actions: PCommandActions ): PControl;
28204 const szActions = sizeof(TCommandActions);
28206 PUSH EBX
28207 PUSH EAX // push AParent
28208 PUSH ECX // push Style
28209 MOVZX ECX, Ctl3D
28210 CALL _NewWindowed
28211 XCHG EBX, EAX
28212 INC [EBX].TControl.fIsControl
28213 INC [EBX].TControl.fVerticalAlign
28214 MOV EAX, Actions
28215 TEST EAX, EAX
28216 JZ @@noActions
28217 LEA EDX, [EBX].TControl.fCommandActions
28218 XOR ECX, ECX
28219 MOV CL, szActions
28220 CALL System.Move
28221 @@noActions:
28222 POP EDX // pop Style
28223 OR EDX, WS_CLIPSIBLINGS or WS_CLIPCHILDREN
28224 MOV byte ptr [EBX].TControl.fLookTabKeys, $0F
28225 CMP [EBX].TControl.fCtl3D, 0
28226 JZ @@noCtl3D
28227 AND EDX, not WS_BORDER
28228 OR byte ptr [EBX].TControl.fExStyle + 1, WS_EX_CLIENTEDGE shr 8
28229 @@noCtl3D:
28230 MOV [EBX].TControl.fStyle, EDX
28231 TEST EDX, WS_VISIBLE
28232 SETNZ AL
28233 MOV [EBX].TControl.fVisible, AL
28234 TEST EDX, WS_TABSTOP
28235 POP ECX // pop AParent
28236 PUSHFD
28237 JECXZ @@noParent
28238 MOV EAX, [ECX].TControl.fCursor
28239 MOV [EBX].TControl.fCursor, EAX
28240 XCHG EAX, ECX
28241 CALL TControl.ParentForm
28242 XCHG ECX, EAX
28243 JECXZ @@noParent
28244 INC [ECX].TControl.fTabOrder
28245 MOV EDX, [ECX].TControl.fTabOrder
28246 MOV [EBX].TControl.fTabOrder, EDX
28247 @@noParent:
28248 POPFD
28249 JZ @@noTabStop
28250 INC [EBX].TControl.fTabstop
28251 JECXZ @@noTabstop
28252 XCHG EAX, ECX
28253 MOV ECX, [EAX].TControl.FCurrentControl
28254 INC ECX
28255 LOOP @@noTabStop
28256 MOV [EAX].TControl.FCurrentControl, EBX
28257 @@noTabStop:
28258 MOVZX EDX, [CtlIdCount]
28259 INC [CtlIdCount]
28260 MOV [EBX].TControl.fMenu, EDX
28261 MOV EDX, offset[WndProcCtrl]
28262 MOV EAX, EBX
28263 CALL TControl.AttachProc
28264 XCHG EAX, EBX
28265 POP EBX
28266 end;
28267 {$ELSE ASM_VERSION} //Pascal
28268 function _NewControl( AParent: PControl; ControlClassName: PChar;
28269 Style: DWORD; Ctl3D: Boolean; Actions: PCommandActions ): PControl;
28270 var Form: PControl;
28271 begin
28272 Result := _NewWindowed( AParent, ControlClassName, Ctl3D );
28273 if Actions <> nil then
28274 Result.fCommandActions := Actions^;
28275 Result.fIsControl := True;
28276 Result.fStyle := Style or WS_CLIPSIBLINGS or WS_CLIPCHILDREN;
28277 Result.fVerticalAlign := vaTop;
28278 Result.fVisible := (Style and WS_VISIBLE) <> 0;
28279 Result.fTabstop := (Style and WS_TABSTOP) <> 0;
28280 if (AParent <> nil) then
28281 begin
28282 Inc( AParent.ParentForm.fTabOrder );
28283 Result.fTabOrder := AParent.ParentForm.fTabOrder;
28284 Result.fCursor := AParent.fCursor;
28285 end;
28286 Result.fLookTabKeys := [ tkTab, tkLeftRight, tkUpDown, tkPageUpPageDn ];
28287 if Result.fCtl3D then
28288 begin
28289 Result.fStyle := Result.fStyle and not WS_BORDER;
28290 Result.fExStyle := Result.fExStyle or WS_EX_CLIENTEDGE;
28291 end;
28292 if (Style and WS_TABSTOP) <> 0 then
28293 begin
28294 Form := Result.ParentForm;
28295 if Form <> nil then
28296 if Form.FCurrentControl = nil then
28297 Form.FCurrentControl := Result;
28298 end;
28299 //Result.fCreateParamsExt := CreateParams2;
28300 Result.fMenu := CtlIdCount;
28301 Inc( CtlIdCount );
28302 Result.AttachProc( WndProcCtrl );
28303 end;
28304 {$ENDIF ASM_VERSION}
28305 //[END _NewControl]
28307 //===================== Button ========================//
28309 //[function TControl.SetButtonIcon]
28310 function TControl.SetButtonIcon(aIcon: HIcon): PControl;
28311 var PrevImg: THandle;
28312 begin
28313 Style := Style or BS_ICON;
28314 PrevImg := Perform( BM_SETIMAGE, IMAGE_ICON, aIcon );
28315 if PrevImg <> 0 then
28316 DeleteObject( PrevImg );
28317 Result := @ Self;
28318 end;
28320 //[function TControl.SetButtonBitmap]
28321 function TControl.SetButtonBitmap(aBmp: HBitmap): PControl;
28322 var PrevImg: THandle;
28323 begin
28324 Style := Style or BS_BITMAP;
28325 PrevImg := Perform( BM_SETIMAGE, IMAGE_BITMAP, aBmp );
28326 if PrevImg <> 0 then
28327 DeleteObject( PrevImg );
28328 Result := @ Self;
28329 end;
28331 {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}
28332 //[function WndProcBtnReturnClick]
28333 function WndProcBtnReturnClick( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
28334 begin
28335 Result := FALSE;
28336 if ((Msg.message = WM_KEYDOWN) or (Msg.message = WM_KEYUP) or
28337 (Msg.message = WM_CHAR)) and (Msg.wParam = 13) then
28338 Msg.wParam := 32;
28339 end;
28340 {$ENDIF}
28342 {$IFDEF USE_CONSTRUCTORS}
28343 //[function NewButton]
28344 function NewButton( AParent: PControl; const Caption: String ): PControl;
28345 begin
28346 new( Result, CreateButton( AParent, Caption ) );
28347 end;
28348 {$ELSE USE_CONSTRUCTORS}
28350 {$IFDEF ASM_VERSION}
28351 const ButtonClass: array[ 0..6 ] of Char = ( 'B','U','T','T','O','N',#0 );
28352 {$ENDIF ASM_VERSION}
28354 //[FUNCTION NewButton]
28355 {$IFDEF ASM_VERSION}
28356 function NewButton( AParent: PControl; const Caption: String ): PControl;
28357 const szActions = sizeof(TCommandActions);
28359 PUSH EDX
28361 PUSH 0
28362 PUSH offset[ButtonActions]
28364 MOV EDX, offset[ButtonClass]
28365 MOV ECX, WS_VISIBLE or WS_CHILD or BS_PUSHLIKE or WS_TABSTOP
28366 CALL _NewControl
28367 INC [EAX].TControl.fIgnoreDefault
28368 MOV EDX, [EAX].TControl.fBoundsRect.Top
28369 ADD EDX, 22
28370 MOV [EAX].TControl.fBoundsRect.Bottom, EDX
28371 MOV [EAX].TControl.fTextAlign, taCenter
28372 INC [EAX].TControl.fIsButton
28374 POP EDX
28375 PUSH EAX
28376 CALL TControl.SetCaption
28377 POP EAX
28378 {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}
28379 PUSH EAX
28380 MOV EDX, offset[WndProcBtnReturnClick]
28381 CALL TControl.AttachProc
28382 POP EAX
28383 {$ENDIF}
28384 end;
28385 {$ELSE ASM_VERSION} //Pascal
28386 function NewButton( AParent: PControl; const Caption: String ): PControl;
28387 begin
28388 Result := _NewControl( AParent, 'BUTTON',
28389 WS_VISIBLE or WS_CHILD or
28390 BS_PUSHLIKE or WS_TABSTOP, False, @ButtonActions );
28391 Result.fIgnoreDefault := TRUE;
28392 Result.fCtl3D := TRUE;
28393 with Result.fBoundsRect do
28394 Bottom := Top + 22;
28395 Result.fTextAlign := taCenter;
28396 Result.Caption := Caption;
28397 Result.fIsButton := TRUE;
28398 {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}
28399 Result.AttachProc( WndProcBtnReturnClick );
28400 {$ENDIF}
28401 end;
28402 {$ENDIF ASM_VERSION}
28403 //[END NewButton]
28405 {$ENDIF USE_CONSTRUCTORS}
28407 //----------------- BitBtn -----------------------
28409 //[FUNCTION WndProc_DrawItem]
28410 {$IFDEF ASM_VERSION}
28411 function WndProc_DrawItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer )
28412 : Boolean;
28413 asm //cmd //opd
28414 CMP word ptr [EDX].TMsg.message, WM_DRAWITEM
28415 JNZ @@ret_false
28416 MOV EAX, [EDX].TMsg.lParam
28417 MOV ECX, [EAX].TDrawItemStruct.hwndItem
28418 JECXZ @@ret_false
28419 PUSH EDX
28420 PUSH offset[ID_SELF]
28421 PUSH ECX
28422 CALL GetProp
28423 POP EDX
28424 TEST EAX, EAX
28425 JZ @@ret_false
28426 PUSH [EDX].TMsg.lParam
28427 PUSH [EDX].TMsg.wParam
28428 PUSH CN_DRAWITEM
28429 PUSH EAX
28430 CALL TControl.Perform
28431 MOV AL, 1
28433 @@ret_false:
28434 XOR EAX, EAX
28435 end;
28436 {$ELSE ASM_VERSION} //Pascal
28437 function WndProc_DrawItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer )
28438 : Boolean;
28439 var DI: PDrawItemStruct;
28440 Control: PControl;
28441 begin
28442 Result := FALSE;
28443 if Msg.message = WM_DRAWITEM then
28444 begin
28445 DI := Pointer( Msg.lParam );
28446 Control := Pointer( GetProp( DI.hwndItem, ID_SELF ) );
28447 if Control <> nil then
28448 begin
28449 {Rslt := Integer(
28450 Control.OnDrawItem( Control, DI.hDC, DI.rcItem, DI.itemID,
28451 TDrawAction( Byte( DI.itemAction ) ),
28452 TDrawState( Word( DI.itemState ) ) ) );}
28453 Rslt := Control.Perform( CN_DRAWITEM, Msg.wParam, Msg.lParam );
28454 Result := TRUE;
28455 end;
28456 //else Rslt := 0;
28457 end;
28458 end;
28459 {$ENDIF ASM_VERSION}
28460 //[END WndProc_DrawItem]
28462 //[function ExcludeAmpersands]
28463 function ExcludeAmpersands( Self_: PControl; const S: String ): String;
28464 var I: Integer;
28465 begin
28466 Result := S;
28467 if not Self_.FBitBtnDrawMnemonic then Exit;
28468 for I := Length( Result ) downto 1 do
28469 begin
28470 if Result[ I ] = '&' then
28471 Delete( Result, I, 1 );
28472 end;
28473 end;
28475 //[procedure BitBtnExtDraw]
28476 procedure BitBtnExtDraw( Self_: PControl; DC: HDC; X, Y: Integer; const R: TRect;
28477 const CapText, CapTxtOrig: String; Color: TColor );
28478 var I, J, W, H: Integer;
28479 Sz: TSize;
28480 Pen, OldPen: HPen;
28481 begin
28482 if not Self_.FBitBtnDrawMnemonic then Exit;
28483 J := 0;
28484 for I := 1 to Length( CapTxtOrig ) do
28485 begin
28486 if CapTxtOrig[ I ] <> '&' then
28487 Inc( J )
28488 else
28489 begin
28490 Windows.GetTextExtentPoint32( DC, PChar( CapText ), J, Sz );
28491 W := Sz.cx;
28492 Windows.GetTextExtentPoint32( DC, '_', 1, Sz );
28493 H := Sz.cy - 1;
28494 Windows.GetTextExtentPoint32( DC, @ CapTxtOrig[ I + 1 ], 1, Sz );
28495 Windows.MoveToEx( DC, X + W, Y + H, nil );
28497 Pen := CreatePen( PS_SOLID, 0, Color2RGB( Color ) );
28498 OldPen := SelectObject( DC, Pen );
28500 Windows.LineTo( DC, X + W + Sz.cx, Y + H );
28502 SelectObject( DC, OldPen );
28503 DeleteObject( Pen );
28504 end;
28505 end;
28506 end;
28508 //[procedure TControl.SetBitBtnDrawMnemonic]
28509 procedure TControl.SetBitBtnDrawMnemonic(const Value: Boolean);
28510 begin
28511 FBitBtnDrawMnemonic := Value;
28512 FBitBtnGetCaption := ExcludeAmpersands;
28513 FBitBtnExtDraw := BitBtnExtDraw;
28514 Invalidate;
28515 end;
28517 //[function TControl.GetBitBtnImgIdx]
28518 function TControl.GetBitBtnImgIdx: Integer;
28519 begin
28520 Result := LoWord( fGlyphCount );
28521 end;
28523 //[procedure TControl.SetBitBtnImgIdx]
28524 procedure TControl.SetBitBtnImgIdx(const Value: Integer);
28525 begin
28526 if not( bboImageList in fBitBtnOptions ) then Exit;
28527 fGlyphCount := HiWord( fGlyphCount ) or (Value and $FFFF);
28528 Invalidate;
28529 end;
28531 //[function TControl.GetBitBtnImageList]
28532 function TControl.GetBitBtnImageList: THandle;
28533 begin
28534 Result := 0;
28535 if bboImageList in fBitBtnOptions then
28536 Result := fGlyphBitmap;
28537 end;
28539 //[procedure TControl.SetBitBtnImageList]
28540 procedure TControl.SetBitBtnImageList(const Value: THandle);
28541 begin
28542 fGlyphBitmap := Value;
28543 if Value <> 0 then
28544 begin
28545 fBitBtnOptions := fBitBtnOptions + [ bboImageList ];
28546 ImageList_GetIconSize( Value, fGlyphWidth, fGlyphHeight );
28548 else
28549 fBitBtnOptions := fBitBtnOptions - [ bboImageList ];
28550 Invalidate;
28551 end;
28553 //[FUNCTION WndProcBitBtn]
28554 {$IFDEF ASM_noVERSION} // remove &-s from view //+ TextShift & if Y < 0 then Y := 0; // + glyph + TextShift if not glyphOver
28555 function WndProcBitBtn( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
28556 const szBitmapInfo = sizeof(TBitmapInfo);
28558 CMP word ptr [EDX].TMsg.message, WM_LBUTTONDBLCLK
28559 JNZ @@noWM_LBUTTONDBLCLK
28560 PUSH ECX
28561 PUSH [EDX].TMsg.wParam
28562 PUSH [EDX].TMsg.lParam
28563 PUSH WM_LBUTTONDOWN
28564 PUSH EAX
28565 CALL TControl.Perform
28566 POP ECX
28567 MOV [ECX], EAX
28568 MOV AL, 1
28570 @@noWM_LBUTTONDBLCLK:
28571 PUSH EBX
28572 CMP [EDX].TMsg.message, CN_DRAWITEM
28573 JNZ @@noCN_DRAWITEM
28574 PUSH EDI
28575 PUSH ESI
28576 XCHG EDI, EAX // EDI = @Self
28577 MOV dword ptr [ECX], 1
28578 MOV ESI, [EDX].TMsg.lParam // ESI = DIS
28579 XOR EBX, EBX // G = 0
28580 MOV EAX, [ESI].TDrawItemStruct.itemState
28581 TEST byte ptr [EDI].TControl.fBitBtnOptions, 8 //1 shl Ord(bboFixed)
28582 JNZ @@fixed_in_options
28583 {$IFDEF PARANOIA}
28584 DB $A8, ODS_SELECTED
28585 {$ELSE}
28586 TEST AL, ODS_SELECTED
28587 {$ENDIF}
28588 JZ @@not1
28589 JMP @@1
28590 @@fixed_in_options:
28591 TEST byte ptr [EDI].TControl.fChecked, 1
28592 JZ @@not1
28593 @@1: INC EBX
28594 @@not1:
28595 {$IFDEF PARANOIA}
28596 DB $A8, ODS_DISABLED
28597 {$ELSE}
28598 TEST AL, ODS_DISABLED
28599 {$ENDIF}
28600 JZ @@not2
28601 MOV BL, 2
28602 @@not2: TEST EBX, EBX
28603 JNZ @@not3
28604 {$IFDEF PARANOIA}
28605 DB $A8, ODS_FOCUS
28606 {$ELSE}
28607 TEST AL, ODS_FOCUS
28608 {$ENDIF}
28609 JZ @@not3
28610 MOV BL, 3
28611 @@not3: CMP [EDI].TControl.fMouseInControl, BH
28612 JZ @@not4
28613 TEST EBX, EBX
28614 JZ @@4
28615 CMP BL, 3
28616 JNZ @@not4
28617 @@4: MOV BL, 4
28618 @@not4: MOV ECX, [EDI].TControl.fOnBitBtnDraw.TMethod.Code
28619 TEST ECX, ECX
28620 JZ @@noOnBitBtnDraw
28621 //JECXZ @@noOnBitBtnDraw
28622 MOV EAX, [EDI].TControl.fCanvas
28623 PUSH EAX
28624 TEST EAX, EAX
28625 JZ @@noCanvas
28626 MOV EDX, [ESI].TDrawItemStruct.hDC
28627 CALL TCanvas.SetHandle
28628 @@noCanvas:
28629 MOV EAX, [EDI].TControl.fOnBitBtnDraw.TMethod.Data
28630 MOV EDX, EDI
28631 PUSH EBX
28632 XCHG ECX, EBX
28633 CALL EBX
28634 POP EBX
28635 POP ECX // Canvas
28636 PUSH EAX
28637 JECXZ @@noCanvas2
28638 XCHG EAX, ECX
28639 XOR EDX, EDX
28640 CALL TCanvas.SetHandle
28641 @@noCanvas2:
28642 POP EAX
28643 TEST AL, AL
28644 JNZ @@exit_draw
28645 @@noOnBitBtnDraw:
28646 TEST byte ptr [EDI].TControl.fBitBtnOptions, 2 //1 shl Ord(bboNoBorder)
28647 JNZ @@noborder
28648 TEST byte ptr [ESI].TDrawItemStruct.itemState, ODS_FOCUS
28649 JZ @@noDefaultBorder
28650 PUSH BLACK_BRUSH
28651 CALL GetStockObject
28652 LEA EDX, [ESI].TDrawItemStruct.rcItem
28653 OR ECX, -1
28654 PUSH ECX
28655 PUSH ECX
28656 PUSH EDX
28657 PUSH EAX
28658 PUSH EDX
28659 PUSH [ESI].TDrawItemStruct.hDC
28660 CALL Windows.FrameRect
28661 CALL InflateRect
28662 XOR ECX, ECX
28663 JMP @@noFlat
28664 @@noDefaultBorder:
28665 MOVZX ECX, [EDI].TControl.fFlat
28666 JECXZ @@noFlat
28667 AND CL, [EDI].TControl.fMouseInControl
28668 JZ @@noborder
28669 @@noFlat:
28670 TEST byte ptr [ESI].TDrawItemStruct.itemState, ODS_SELECTED
28671 MOV CL, BDR_SUNKENOUTER or BDR_SUNKENINNER
28672 JNZ @@border_sunken
28673 MOV CL, BDR_RAISEDOUTER or BDR_RAISEDINNER
28674 @@border_sunken:
28675 LEA EDX, [ESI].TDrawItemStruct.rcItem
28676 OR EAX, -1
28677 PUSH EAX
28678 PUSH EAX
28679 PUSH EDX
28680 PUSH BF_ADJUST or BF_RECT
28681 PUSH ECX
28682 PUSH EDX
28683 PUSH [ESI].TDrawItemStruct.hDC
28684 CALL DrawEdge
28685 CALL InflateRect
28686 @@noborder:
28687 PUSH [ESI].TDrawItemStruct.rcItem.Bottom
28688 PUSH [ESI].TDrawItemStruct.rcItem.Right
28689 PUSH [ESI].TDrawItemStruct.rcItem.Top
28690 PUSH [ESI].TDrawItemStruct.rcItem.Left
28691 MOV EAX, [EDI].TControl.fGlyphWidth
28692 MOV EDX, [EDI].TControl.fGlyphHeight
28693 TEST EAX, EAX
28694 JLE @@noglyph
28695 TEST EDX, EDX
28696 JLE @@noglyph
28697 PUSH EBP
28698 MOV EBP, ESP
28699 // [EBP+4] = TxRect
28701 PUSH EDX // ImgH -> [EBP-4]
28702 PUSH EAX // ImgW -> [EBP-8]
28703 PUSH EDX // OutH -> [EBP-12]
28704 PUSH EAX // OutW -> [EBP-16]
28705 MOV EAX, [ESI].TDrawItemStruct.rcItem.Left // X = DIS.rcItem.Left
28706 MOV EDX, [ESI].TDrawItemStruct.rcItem.Top // Y = DIS.rcItem.Top
28707 MOV ECX, [ESI].TDrawItemStruct.rcItem.Bottom
28708 SUB ECX, EDX
28709 PUSH ECX // H -> [EBP-20]
28710 MOV ECX, [ESI].TDrawItemStruct.rcItem.Right
28711 SUB ECX, EAX
28712 PUSH ECX // W -> [EBP-24]
28713 MOVZX ECX, [EDI].TControl.fGlyphLayout
28714 PUSH EBX
28715 INC ECX
28716 LOOP @@noGlyphLeft
28717 MOV EBX, EAX // X
28718 ADD EBX, [EBP-16] // +OutW
28719 MOV [EBP+4].TRect.Left, EBX // TxRect.Left = X+OutW
28720 JMP @@centerY
28721 @@noGlyphLeft:
28722 LOOP @@noGlyphTop
28723 MOV EBX, EDX // Y
28724 ADD EBX, [EBP-12] // +OutH
28725 MOV [EBP+4].TRect.Top, EBX // TxRect.Top = Y+OutH
28726 LOOP @@centerX // always JMP, ECX := -1
28727 @@noGlyphTop:
28728 LOOP @@noGlyphRight
28729 MOV EAX, [ESI].TDrawItemStruct.rcItem.Right
28730 SUB EAX, [EBP-16] // -OutW -> X
28731 MOV [EBP+4].TRect.Right, EAX
28732 @@centerY:
28733 MOV EBX, [EBP-20] // H
28734 SUB EBX, [EBP-12] // -OutH
28735 JLE @@noGlyphRight
28736 SAR EBX, 1
28737 ADD EDX, EBX // Y = Y + (H-OutH)/2
28738 @@noGlyphRight:
28739 LOOP @@noGlyphBottom
28740 MOV EDX, [ESI].TDrawItemStruct.rcItem.Bottom
28741 SUB EDX, [EBP-12] // -OutH -> Y
28742 MOV [EBP+4].TRect.Bottom, EDX
28743 LOOP @@centerX // always JMP, ECX := -1
28744 @@noGlyphBottom:
28745 LOOP @@noGlyphOver
28746 @@centerX:
28747 MOV EBX, [EBP-24] // W
28748 SUB EBX, [EBP-16] // -OutW
28749 SHR EBX, 1 // /2
28750 ADD EAX, EBX // +EAX, X = X + (W-OutW)/2
28751 JECXZ @@centerY
28752 @@noGlyphOver:
28753 MOV ECX, [ESI].TDrawItemStruct.rcItem.Left
28754 CMP EAX, ECX
28755 JGE @@ok1
28756 XCHG EAX, ECX
28757 @@ok1: CMP EDX, [ESI].TDrawItemStruct.rcItem.Top
28758 {$IFDEF USE_CMOV}
28759 CMOVL EDX, [ESI].TDrawItemStruct.rcItem.Top
28760 {$ELSE}
28761 JGE @@ok2
28762 MOV EDX, [ESI].TDrawItemStruct.rcItem.Top
28763 @@ok2: {$ENDIF}
28765 MOV ECX, [ESI].TDrawItemStruct.rcItem.Right
28766 SUB ECX, EAX
28767 CMP [EBP-16], ECX
28768 JLE @@ok3
28769 MOV [EBP-16], ECX // OutW := rcItem.Right - X;
28770 @@ok3: MOV ECX, [ESI].TDrawItemStruct.rcItem.Bottom
28771 SUB ECX, EDX
28772 CMP ECX, [EBP-12]
28773 JGE @@ok4
28774 MOV [EBP-12], ECX // OutH := rcItem.Bottom - Y;
28775 @@ok4:
28776 POP EBX // EBX = G
28777 TEST byte ptr [EDI].TControl.fBitBtnOptions, 1 //1 shl Ord(bboImageList)
28778 JZ @@draw_bitmap
28779 MOVZX ECX, word ptr [EDI].TControl.fGlyphCount
28780 CMP word ptr [EDI].TControl.fGlyphCount + 2, BX
28781 JLE @@no_add_glyphIdx
28782 ADD ECX, EBX
28783 @@no_add_glyphIdx:
28784 XOR EBX, EBX
28785 PUSH ILD_TRANSPARENT // Flags = 1 (ILD_TRANSPARENT)
28786 PUSH EBX // Blend = 0
28787 PUSH -1 // Bk = CLR_NONE
28788 PUSH EBX // 0
28789 PUSH EBX // 0
28790 PUSH EDX
28791 PUSH EAX
28792 PUSH [ESI].TDrawItemStruct.hDC
28793 PUSH ECX
28794 PUSH [EDI].TControl.fGlyphBitmap
28795 CMP [EDI].TControl.fTransparent, BL
28796 JNZ @@imgl_transp
28797 MOV EAX, [EDI].TControl.fColor
28798 CALL Color2RGB
28799 MOV [ESP+32], EAX // Bk = Color2RGB(fColor)
28800 MOV [ESP+40], EBX // Flags = 0
28801 @@imgl_transp:
28802 INC EBX
28803 CMP word ptr [EDI].TControl.fGlyphCount + 2, BX
28804 JNZ @@draw_imagelist
28805 DEC byte ptr [ESP+36+3] // $FF, CLR_DEFAULT = $FF000000
28806 TEST byte ptr [ESI].TDrawItemStruct.itemState, ODS_FOCUS
28807 JZ @@draw_imagelist
28808 OR byte ptr [ESP+40], ILD_BLEND25 // Flags != 2
28809 @@draw_imagelist:
28810 CALL ImageList_DrawEx
28811 JMP @@glyph_drawn
28813 @@draw_bitmap:
28814 PUSH EAX // PlaceHold for DC
28815 PUSH EAX // PlaceHold for OldBmp
28816 PUSH SRCCOPY
28817 PUSH dword ptr [EBP-4] // ImgH
28818 PUSH dword ptr [EBP-8] // ImgW
28819 PUSH 0
28820 PUSH EAX // PlaceHold for I
28821 PUSH EAX // PlaceHold for DC
28822 PUSH dword ptr [EBP-12] // OutH
28823 PUSH dword ptr [EBP-16] // OutW
28824 PUSH EDX // Y
28825 PUSH EAX // X
28826 PUSH [ESI].TDrawItemStruct.hDC
28828 PUSH 0
28829 CALL CreateCompatibleDC
28830 MOV [ESP+48], EAX // save DC
28831 MOV [ESP+20], EAX // place DC
28832 PUSH [EDI].TControl.fGlyphBitmap
28833 PUSH EAX
28834 CALL SelectObject
28835 MOV [ESP+44], EAX // save OldBitmap
28836 XOR EAX, EAX
28837 CMP [EDI].TControl.fGlyphCount, EBX
28838 JLE @@no_incGlyIdx
28839 MOV EAX, [EBP-8] // ImgW
28840 IMUL EBX
28841 @@no_incGlyIdx:
28842 MOV [ESP+24], EAX // place I
28843 CALL StretchBlt
28844 CALL FinishDC
28846 @@glyph_drawn:
28847 MOV ESP, EBP
28848 POP EBP
28850 @@noglyph:
28851 TEST byte ptr[EDI].TControl.fBitBtnOptions, 4 //1 shl Ord(bboNoCaption)
28852 JNZ @@noCaption
28855 POP EAX
28856 PUSH EAX
28857 MOV EDX, [ESP].TRect.Right
28858 CMP EDX, EAX
28859 JLE @@noCaption
28860 MOV EDX, [ESP].TRect.Bottom
28861 CMP EDX, [ESP].TRect.Top
28862 JLE @@noCaption
28864 XOR EBX, EBX
28865 PUSH EBX // > CapText
28866 MOV EDX, ESP
28867 MOV EAX, EDI
28868 CALL TControl.GetCaption
28869 PUSH EBX // > Bk
28870 PUSH EBX // > Blend
28871 CMP [EDI].TControl.fTransparent, BL
28872 MOV BL, ETO_CLIPPED
28873 JNZ @@drwTxTransparent
28874 CMP [EDI].TControl.fGlyphLayout, glyphOver
28875 JNZ @@drwTxOpaque
28876 @@drwTxTransparent:
28877 PUSH TRANSPARENT
28878 PUSH [ESI].TDrawItemStruct.hDC
28879 CALL SetBkMode
28880 MOV [ESP+4], EAX // Bk := SetBkMode( DIS.hDC, TRANSPARENT )
28881 JMP @@drwTx1
28882 @@drwTxOpaque:
28883 MOV BL, ETO_CLIPPED or ETO_OPAQUE
28884 MOV EAX, [EDI].TControl.fColor
28885 CALL Color2RGB
28886 PUSH EAX
28887 PUSH [ESI].TDrawItemStruct.hDC
28888 CALL SetBkColor
28889 POP ECX
28890 PUSH EAX // Blend := SetBkColor(DIS.hDC,fColor)
28891 @@drwTx1:
28892 PUSH 0 // > OldFont
28893 PUSH 0 // > OldTextColor
28895 PUSH 0 // push <nil>
28896 MOV EDX, [ESP+20] // CapText
28897 CALL EDX2PChar
28898 PUSH dword ptr [EDX-4] // push Length(CapText)
28899 PUSH EDX // push PChar(CapText)
28900 LEA EAX, [ESP+32]
28901 PUSH EAX // push @TxRect
28902 PUSH EBX // push Flags
28904 MOV EBX, [ESI].TDrawItemStruct.hDC
28906 MOV ECX, [EDI].TControl.fFont
28907 JECXZ @@drwTx_noFont
28908 XCHG EAX, ECX
28909 CALL TGraphicTool.GetHandle
28910 PUSH EAX
28911 PUSH EBX
28912 CALL SelectObject
28913 MOV [ESP+24], EAX // OldFont := SelectObject...
28914 @@drwTx_noFont:
28915 MOV EAX, [EDI].TControl.fTextColor
28916 CALL Color2RGB
28917 PUSH EAX
28918 PUSH EBX
28919 CALL SetTextColor
28920 MOV [ESP+20], EAX // OldTextColor := SetTextColor...
28922 PUSH EAX
28923 PUSH EAX
28924 PUSH ESP
28925 MOV ECX, [ESP+48] // ECX = CapText
28926 XOR EAX, EAX
28927 JECXZ @@drwTx0
28928 MOV EAX, [ECX-4] // EAX = Length(CapText)
28929 @@drwTx0:
28930 PUSH EAX
28931 PUSH ECX
28932 PUSH EBX
28933 CALL GetTextExtentPoint32
28934 POP ECX // ECX = TextSz.cx
28935 POP EDX // EDX = TextSz.cy
28936 MOV EAX, [ESP+40].TRect.Bottom
28937 SUB EAX, [ESP+40].TRect.Top
28938 SUB EAX, EDX
28939 JGE @@yOk
28940 XOR EAX, EAX
28941 @@yOk: SHR EAX, 1
28942 ADD EAX, [ESP+40].TRect.Top
28943 PUSH EAX // push Y
28944 MOV EDX, [ESP+44].TRect.Right
28945 MOV EAX, [ESP+44].TRect.Left // EAX = TxRect.Left
28946 SUB EDX, EAX // EDX = W
28947 PUSH EAX
28948 CMP [EDI].TControl.fTextAlign, taRight
28949 JL @@chk_X
28950 JE @@alignR
28951 SUB ECX, EDX
28952 SAR ECX, 1
28953 JMP @@alignC
28954 @@alignR:
28955 ADD EAX, EDX
28956 @@alignC:
28957 SUB EAX, ECX
28958 @@chk_X:POP EDX
28959 CMP EAX, EDX
28960 JGE @@xOk
28961 XCHG EAX, EDX
28962 @@xOk: PUSH EAX // push X
28963 PUSH EBX // push hDC
28964 CALL ExtTextOut
28966 PUSH EBX
28967 CALL SetTextColor
28968 POP ECX
28969 JECXZ @@noRestoreFont
28970 PUSH ECX
28971 PUSH EBX
28972 CALL SelectObject
28973 @@noRestoreFont:
28974 POP ECX // Blend
28975 JECXZ @@restoreBk
28976 PUSH ECX
28977 PUSH EBX
28978 CALL SetBkColor
28979 POP ECX
28980 JMP @@delCaption
28981 @@restoreBk:
28982 PUSH EBX
28983 CALL SetBkMode
28984 @@delCaption:
28985 CALL RemoveStr
28987 @@noCaption:
28988 ADD ESP, 16
28990 @@exit_draw:
28991 POP ESI
28992 POP EDI
28993 POP EBX
28994 MOV AL, 1
28997 @@noCN_DRAWITEM:
28998 CMP word ptr [EDX].TMsg.message, WM_LBUTTONDOWN
28999 JZ @@doDown
29000 CMP word ptr [EDX].TMsg.message, WM_KEYDOWN
29001 JNZ @@noWM_LBUTTONDOWN
29002 CMP [EDX].TMsg.wParam, 32
29003 JNZ @@noWM_LBUTTONDOWN
29004 @@doDown:
29005 PUSH EDX
29006 XCHG EBX, EAX
29008 CALL @@fixed_proc
29009 MOV ECX, [EBX].TControl.fRepeatInterval
29010 JECXZ @@exit_LBUTTONDOWN
29011 //MOV EAX, EBX
29012 //CALL TControl.DoClick
29013 POP EDX
29014 PUSH EDX
29015 CMP word ptr [EDX].TMsg.message, WM_KEYDOWN
29016 JZ @@not_SetTimer
29017 PUSH 0
29018 PUSH [EBX].TControl.fRepeatInterval
29019 PUSH 1
29020 PUSH [EBX].TControl.fHandle
29021 CALL SetTimer
29022 @@exit_LBUTTONDOWN:
29023 @@not_SetTimer:
29024 POP EDX
29025 JMP @@invalidate
29027 @@noWM_LBUTTONDOWN:
29028 CMP word ptr [EDX].TMsg.message, WM_TIMER
29029 JNZ @@noWM_TIMER
29031 XCHG EBX, EAX
29032 PUSH 0
29033 PUSH 0
29034 PUSH BM_GETSTATE
29035 PUSH EBX
29036 CALL TControl.Perform
29037 {$IFDEF PARANOIA}
29038 DB $A8, 4
29039 {$ELSE}
29040 TEST AL, BST_PUSHED
29041 {$ENDIF}
29042 JNZ @@pushed
29043 PUSH 1
29044 PUSH [EBX].TControl.fHandle
29045 CALL KillTimer
29046 CALL ReleaseCapture
29047 JMP @@noWM_TIMER
29048 @@fixed_proc:
29049 TEST byte ptr [EBX].TControl.fBitBtnOptions, 8 // bboFixed
29050 JZ @@not_fixed
29051 XOR [EBX].TControl.fChecked, 1
29052 MOV ECX, [EBX].TControl.fOnChange.TMethod.Code
29053 JECXZ @@not_fixed
29054 MOV EAX, [EBX].TControl.fOnChange.TMethod.Data
29055 MOV EDX, EBX
29056 JMP ECX
29057 @@pushed:
29058 CALL @@fixed_proc
29059 MOV EAX, EBX
29060 CALL TControl.DoClick
29061 @@invalidate:
29062 XCHG EAX, EBX
29063 CALL TControl.Invalidate
29064 @@noWM_TIMER:
29065 XOR EAX, EAX
29066 POP EBX
29067 @@not_fixed:
29068 end;
29069 {$ELSE ASM_VERSION} //Pascal
29070 function WndProcBitBtn( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
29071 var DIS: PDrawItemStruct;
29072 IsDown, IsDefault, IsDisabled: Boolean;
29073 Flags: Integer;
29074 X, Y, W, H, ImgW, ImgH, OutW, OutH, I, G, Bk, Blend: Integer;
29075 //BI: TBitmapInfo;
29076 //Dib: TDibSection;
29077 TxRect: TRect;
29078 OldFont: HFont;
29079 OldTextColor: TColor;
29080 CapText, CapTxtOrig: String;
29081 TextSz: TSize;
29082 DC: HDC;
29083 OldBmp: HBitmap;
29084 Handled: Boolean;
29085 //Br: HBrush;
29086 begin
29087 Result := False;
29088 if (Msg.message = WM_LBUTTONDBLCLK) then
29089 begin
29090 Rslt := Self_.Perform( WM_LBUTTONDOWN, Msg.wParam, Msg.lParam );
29091 Result := True;
29092 Exit;
29093 end;
29094 if (Msg.message = CN_DRAWITEM) then
29095 begin
29096 Result := True;
29097 Rslt := 1;
29098 DIS := Pointer( Msg.lParam );
29099 IsDown := DIS.itemState and ODS_SELECTED <> 0;
29100 IsDefault := DIS.itemState and ODS_FOCUS <> 0;
29101 IsDisabled := DIS.itemState and ODS_DISABLED <> 0;
29102 G := 0;
29103 if IsDown and not(bboFixed in Self_.fBitBtnOptions)
29104 or (bboFixed in Self_.fBitBtnOptions) and Self_.fChecked then
29105 G := 1;
29106 if IsDisabled then
29107 G := 2;
29108 if (G = 0) and IsDefault then
29109 G := 3;
29110 if ((G = 0) or (G = 3)) and Self_.MouseInControl then
29111 G := 4;
29112 if Assigned( Self_.fOnBitBtnDraw ) then
29113 begin
29114 if Assigned( Self_.fCanvas ) then
29115 Self_.fCanvas.SetHandle( DIS.hDC );
29116 Handled := Self_.fOnBitBtnDraw( Self_, G );
29117 if Assigned( Self_.fCanvas ) then
29118 Self_.fCanvas.SetHandle( 0 );
29119 if Handled then Exit;
29120 end;
29121 if not ( bboNoBorder in Self_.fBitBtnOptions ) then
29122 begin
29123 if IsDefault then
29124 begin
29125 Windows.FrameRect( DIS.hDC, DIS.rcItem, GetStockObject( BLACK_BRUSH ) );
29126 InflateRect( DIS.rcItem, -1, -1 );
29127 end;
29128 if not Self_.fFlat or Self_.fMouseInControl or IsDefault then
29129 begin
29130 if IsDown then
29131 Flags := BDR_SUNKENOUTER or BDR_SUNKENINNER
29132 else
29133 Flags := BDR_RAISEDOUTER or BDR_RAISEDINNER;
29134 DrawEdge( DIS.hDC, DIS.rcItem, Flags, BF_ADJUST or BF_RECT );
29135 InflateRect( DIS.rcItem, -1, -1 );
29136 end;
29137 end;
29138 TxRect := DIS.rcItem;
29139 if Self_.fGlyphBitmap <> 0 then
29140 begin
29141 ImgW := Self_.fGlyphWidth;
29142 ImgH := Self_.fGlyphHeight;
29143 if (ImgW > 0) and (ImgH > 0) then
29144 begin
29145 OutW := ImgW;
29146 OutH := ImgH;
29147 W := DIS.rcItem.Right - DIS.rcItem.Left;
29148 H := DIS.rcItem.Bottom - DIS.rcItem.Top;
29149 X := DIS.rcItem.Left;
29150 Y := DIS.rcItem.Top;
29151 if isDown and (Self_.fGlyphLayout <> glyphOver) then
29152 begin
29153 Inc( X, Self_.TextShiftX );
29154 Inc( Y, Self_.TextShiftY );
29155 end;
29156 case Self_.fGlyphLayout of
29157 glyphLeft:
29158 begin
29159 Y := Y + (H - OutH) div 2;
29160 TxRect.Left := X + OutW;
29161 end;
29162 glyphTop:
29163 begin
29164 X := X + (W - OutW) div 2;
29165 TxRect.Top := Y + OutH;
29166 end;
29167 glyphRight:
29168 begin
29169 X := DIS.rcItem.Right - OutW;
29170 TxRect.Right := X;
29171 Y := Y + (H - OutH) div 2;
29172 end;
29173 glyphBottom:
29174 begin
29175 Y := DIS.rcItem.Bottom - OutH;
29176 TxRect.Bottom := Y;
29177 X := X + (W - OutW) div 2;
29178 end;
29179 glyphOver:
29180 begin
29181 X := X + (W - OutW) div 2;
29182 Y := Y + (H - OutH) div 2;
29183 end;
29184 end;
29185 if X < DIS.rcItem.Left then
29186 X := DIS.rcItem.Left;
29187 if Y < DIS.rcItem.Top then
29188 Y := DIS.rcItem.Top;
29189 if X + OutW > DIS.rcItem.Right then
29190 OutW := DIS.rcItem.Right - X;
29191 if Y + OutH > DIS.rcItem.Bottom then
29192 OutH := DIS.rcItem.Bottom - Y;
29194 //Br := CreateSolidBrush( Color2RGB( Self_.fColor ) );
29195 //Windows.FillRect( DIS.hDC, MakeRect( X, DIS.rcItem.Top, X + OutW, DIS.rcItem.Bottom ), Br );
29196 //DeleteObject( Br );
29198 if bboImageList in Self_.fBitBtnOptions then
29199 begin
29200 I := LoWord( Self_.fGlyphCount );
29201 if //(HiWord( Self_.fGlyphCount ) > 1) and
29202 (HiWord( Self_.fGlyphCount ) > G) then
29203 I := I + G;
29204 Flags := 0; // ILD_NORMAL
29205 Blend := 0;
29206 if not Self_.fTransparent then
29207 Bk := Color2RGB( Self_.fColor )
29208 else
29209 begin
29210 Bk := Integer(CLR_NONE);
29211 Flags := ILD_TRANSPARENT;
29212 end;
29213 if HiWord( Self_.fGlyphCount ) = 1 then
29214 begin
29215 Blend := Integer(CLR_DEFAULT);
29216 if IsDefault then
29217 Flags := Flags or ILD_BLEND25;
29218 end;
29219 ImageList_DrawEx( Self_.fGlyphBitmap, I, DIS.hDC, X, Y, 0, 0,
29220 Bk, Blend, Flags );
29222 else
29223 begin
29224 DC := CreateCompatibleDC( 0 );
29225 OldBmp := SelectObject( DC, Self_.fGlyphBitmap );
29227 I := 0;
29228 if Self_.fGlyphCount > G then
29229 I := I + G * ImgW;
29230 StretchBlt( DIS.hDC, X, Y, OutW, OutH, DC, I, 0, ImgW, ImgH, SRCCOPY );
29232 SelectObject( DC, OldBmp );
29233 DeleteDC( DC );
29234 end;
29235 end;
29236 end;
29237 if not (bboNoCaption in Self_.fBitBtnOptions) then
29238 //if (Self_.Text <> '') then
29239 if (TxRect.Right > TxRect.Left) and (TxRect.Bottom > TxRect.Top) then
29240 begin
29241 CapText := Self_.Caption;
29242 ///////////////////////////////////////////// added 19 Nov 2001
29243 CapTxtOrig := CapText;
29244 if Assigned( Self_.FBitBtnGetCaption ) then
29245 CapText := Self_.FBitBtnGetCaption( Self_, CapText );
29246 /////////////////////////////////////////////
29248 Bk := 0;
29249 Blend := 0;
29250 Flags := ETO_CLIPPED;
29251 if Self_.fTransparent or (Self_.fGlyphLayout = glyphOver) then
29252 Bk := SetBkMode( DIS.hDC, TRANSPARENT )
29253 else
29254 begin
29255 Flags := Flags or ETO_OPAQUE;
29256 Blend := SetBkColor( DIS.hDC, Color2RGB( Self_.fColor ) );
29257 end;
29258 // Returned previous BkMode is either OPAQUE=1 or TRANSPARENT=2
29260 OldFont := 0;
29261 if assigned( Self_.fFont ) then
29262 OldFont := SelectObject( DIS.hDC, Self_.fFont.Handle );
29263 OldTextColor := SetTextColor( DIS.hDC, Color2RGB( Self_.fTextColor ) );
29265 Windows.GetTextExtentPoint32( DIS.hDC, PChar( CapText ), Length( CapText ),
29266 TextSz );
29267 W := TxRect.Right - TxRect.Left;
29268 H := TxRect.Bottom - TxRect.Top;
29269 Y := TxRect.Top + (H - TextSz.cy) div 2;
29270 case Self_.fTextAlign of
29271 taLeft: X := TxRect.Left;
29272 taCenter: X := TxRect.Left + (W - TextSz.cx) div 2;
29273 else {taRight:} X := TxRect.Right - TextSz.cx;
29274 end;
29275 if isDown then
29276 begin
29277 Inc( X, Self_.TextShiftX );
29278 Inc( Y, Self_.TextShiftY );
29279 end;
29280 if Y < 0 then
29281 Y := 0;
29282 if X < TxRect.Left then
29283 X := TxRect.Left;
29285 Windows.ExtTextOut( DIS.hDC, X, Y, Flags, @TxRect,
29286 PChar( CapText ), Length( CapText ), nil );
29288 //////////////////////////////////////////////////////////////////////////
29289 // added 19 Nov 2001 to provide underlying mnemonic characters
29290 if Assigned( Self_.FBitBtnExtDraw ) then
29291 Self_.FBitBtnExtDraw( Self_, DIS.hDC, X, Y, TxRect, CapText, CapTxtOrig,
29292 OldTextColor );
29293 //////////////////////////////////////////////////////////////////////////
29295 SetTextColor( DIS.hDC, OldTextColor );
29296 if OldFont <> 0 then
29297 SelectObject( DIS.hDC, OldFont );
29299 if Blend = 0 then
29300 SetBkMode( DIS.hDC, Bk )
29301 else
29302 SetBkColor( DIS.hDC, Blend );
29303 end;
29304 end;
29305 if (Msg.message = WM_LBUTTONDOWN) or (Msg.message = WM_KEYDOWN) and (Msg.wParam = 32) then
29306 begin
29307 if bboFixed in Self_.fBitBtnOptions then
29308 begin
29309 Self_.fChecked := not Self_.fChecked;
29310 if Assigned( Self_.fOnChange ) then
29311 Self_.fOnChange( Self_ );
29312 end;
29313 if Self_.fRepeatInterval > 0 then
29314 begin
29315 //Self_.DoClick;
29316 if Msg.message <> WM_KEYDOWN then
29317 SetTimer( Self_.fHandle, 1, Self_.fRepeatInterval, nil );
29318 Self_.Invalidate;
29319 end;
29320 end;
29322 // added 15 Aug 2002 to repaint when focus lost:
29323 if Msg.message = WM_KILLFOCUS then
29324 Self_.Invalidate;
29326 if Msg.message = WM_TIMER then
29327 begin
29328 if Self_.Perform( BM_GETSTATE, 0, 0 ) and BST_PUSHED = 0 then
29329 begin
29330 KillTimer( Self_.fHandle, 1 );
29331 ReleaseCapture;
29333 else
29334 begin
29335 if bboFixed in Self_.fBitBtnOptions then
29336 begin
29337 Self_.fChecked := not Self_.fChecked;
29338 if Assigned( Self_.fOnChange ) then
29339 Self_.fOnChange( Self_ );
29340 end;
29341 Self_.DoClick;
29342 Self_.Invalidate;
29343 end;
29344 end;
29345 end;
29346 {$ENDIF ASM_VERSION}
29347 //[END WndProcBitBtn]
29349 {$IFDEF USE_CONSTRUCTORS}
29350 //[function NewBitBtn]
29351 function NewBitBtn( AParent: PControl; const Caption: String;
29352 Options: TBitBtnOptions; Layout: TGlyphLayout; GlyphBitmap: HBitmap;
29353 GlyphCount: Integer ): PControl;
29354 begin
29355 new( Result, CreateBitBtn( AParent, Caption, Options, Layout, GlyphBitmap, GlyphCount ) );
29356 end;
29357 //[END NewBitBtn]
29358 {$ELSE not_USE_CONSTRUCTORS}
29360 //[FUNCTION NewBitBtn]
29361 {$IFDEF ASM_VERSION}
29362 function NewBitBtn( AParent: PControl; const Caption: String;
29363 Options: TBitBtnOptions; Layout: TGlyphLayout; GlyphBitmap: HBitmap; GlyphCount: Integer ): PControl;
29364 const szBitmapInfo = sizeof(TBitmapInfo);
29366 PUSH EBX
29367 PUSH EDX
29368 PUSH ECX
29370 PUSH 0
29371 PUSH offset[ButtonActions]
29372 MOV EDX, offset[ButtonClass]
29373 MOV ECX, WS_VISIBLE or WS_CHILD or WS_TABSTOP or BS_OWNERDRAW
29374 CALL _NewControl
29375 XCHG EBX, EAX
29376 INC [EBX].TControl.fIgnoreDefault
29377 INC [EBX].TControl.fIsButton
29378 MOV byte ptr [EBX].TControl.fCommandActions.aAutoSzX, 8
29379 MOV byte ptr [EBX].TControl.fCommandActions.aAutoSzY, 8
29380 POP EAX
29381 MOV [EBX].TControl.fBitBtnOptions, AL
29382 MOVZX EDX, Layout
29383 MOV [EBX].TControl.fGlyphLayout, DL
29384 MOV ECX, GlyphBitmap
29385 MOV [EBX].TControl.fGlyphBitmap, ECX
29386 MOV EDX, [EBX].TControl.fBoundsRect.Top
29387 ADD EDX, 22
29388 MOV [EBX].TControl.fBoundsRect.Bottom, EDX
29389 TEST ECX, ECX
29390 JZ @@noGlyphWH
29391 {$IFDEF PARANOIA}
29392 DB $A8, 01
29393 {$ELSE}
29394 TEST AL, bboImageList
29395 {$ENDIF}
29396 JZ @@getBmpWH
29397 PUSH EAX
29398 MOV EAX, ESP
29399 PUSH EAX
29400 MOV EDX, ESP
29401 PUSH EAX
29402 PUSH EDX
29403 PUSH ECX
29404 CALL ImageList_GetIconSize
29405 POP EAX
29406 POP EDX
29407 MOV ECX, GlyphCount
29408 JMP @@WHready
29409 @@getBmpWH:
29410 ADD ESP, -szBitmapInfo
29411 PUSH ESP
29412 PUSH szBitmapInfo
29413 PUSH ECX
29414 CALL GetObject
29415 XCHG ECX, EAX
29416 POP EAX
29417 POP EAX
29418 POP EDX
29419 ADD ESP, szBitmapInfo-12
29420 TEST ECX, ECX
29421 JZ @@noGlyphWH
29422 MOV ECX, GlyphCount
29423 INC ECX
29424 LOOP @@GlyphCountOK
29425 PUSH EAX
29426 PUSH EDX
29427 XCHG EDX, ECX
29428 DIV ECX
29429 XCHG ECX, EAX
29430 POP EDX
29431 POP EAX
29432 @@GlyphCountOK:
29433 CMP ECX, 1
29434 JLE @@WHReady
29435 PUSH EDX
29437 IDIV ECX
29438 POP EDX
29439 @@WHReady:
29440 MOV [EBX].TControl.fGlyphWidth, EAX
29441 MOV [EBX].TControl.fGlyphHeight, EDX
29442 MOV [EBX].TControl.fGlyphCount, ECX
29443 POP ECX // ECX = @ Caption[ 1 ]
29444 PUSH ECX
29445 PUSH EDX
29446 PUSH EAX
29447 TEST EAX, EAX
29448 JLE @@noWidthResize
29449 JECXZ @@addWLeft
29450 CMP [Layout], glyphOver
29451 JE @@addWLeft
29452 MOVZX ECX, byte ptr[ECX]
29453 JECXZ @@addWLeft
29454 // else
29455 CMP [Layout], glyphLeft
29456 JZ @@addWRight
29457 CMP [Layout], glyphRight
29458 JNZ @@noWidthResize
29459 @@addWRight:
29460 ADD [EBX].TControl.fBoundsRect.Right, EAX
29461 ADD [EBX].TControl.fCommandActions.aAutoSzX, AX
29462 JMP @@noWidthResize
29463 @@addWLeft:
29464 // then
29465 ADD EAX, [EBX].TControl.fBoundsRect.Left
29466 MOV [EBX].TControl.fBoundsRect.Right, EAX
29467 MOV byte ptr [EBX].TControl.fCommandActions.aAutoSzX, 0
29468 @@noWidthResize:
29469 TEST EDX, EDX
29470 JLE @@noHeightResize
29471 CMP [Layout], glyphTop
29472 JE @@addHBottom
29473 CMP [Layout], glyphBottom
29474 JNE @@addHTop
29475 @@addHBottom:
29476 ADD [EBX].TControl.fBoundsRect.Bottom, EDX
29477 ADD [EBX].TControl.fCommandActions.aAutoSzY, DX
29478 JMP @@noHeightResize
29479 @@addHTop:
29480 ADD EDX, [EBX].TControl.fBoundsRect.Top
29481 MOV [EBX].TControl.fBoundsRect.Bottom, EDX
29482 MOV [EBX].TControl.fCommandActions.aAutoSzY, 0
29483 @@noHeightResize:
29484 POP ECX
29485 POP EAX
29487 MOV DL, 4
29488 TEST [EBX].TControl.fBitBtnOptions, 2 //1 shl bboNoBorder
29489 JNZ @@noBorderResize
29490 JECXZ @@noBorderWinc
29491 ADD [EBX].TControl.fBoundsRect.Right, EDX
29492 CMP [EBX].TControl.fCommandActions.aAutoSzX, 0
29493 JZ @@noBorderWinc
29494 ADD [EBX].TControl.fCommandActions.aAutoSzX, DX
29495 @@noBorderWinc:
29496 TEST EAX, EAX
29497 JLE @@noBorderResize
29498 ADD [EBX].TControl.fBoundsRect.Bottom, EDX
29499 CMP [EBX].TControl.fCommandActions.aAutoSzY, 0
29500 JZ @@noBorderResize
29501 ADD [EBX].TControl.fCommandActions.aAutoSzY, DX
29502 @@noBorderResize:
29503 @@noGlyphWH:
29504 MOV ECX, [EBX].TControl.fParent
29505 JECXZ @@notAttach2Parent
29506 XCHG EAX, ECX
29507 MOV EDX, offset[WndProc_DrawItem]
29508 CALL TControl.AttachProc
29509 @@notAttach2Parent:
29510 MOV EAX, EBX
29511 MOV EDX, offset[WndProcBitBtn]
29512 CALL TControl.AttachProc
29513 MOV EAX, EBX
29514 POP EDX
29515 CALL TControl.SetCaption
29516 MOV [EBX].TControl.fTextAlign, taCenter
29517 {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}
29518 MOV EAX, EBX
29519 MOV EDX, offset[WndProcBtnReturnClick]
29520 CALL TControl.AttachProc
29521 {$ENDIF}
29522 XCHG EAX, EBX
29523 POP EBX
29524 end;
29525 {$ELSE ASM_VERSION} //Pascal
29526 function NewBitBtn( AParent: PControl; const Caption: String;
29527 Options: TBitBtnOptions; Layout: TGlyphLayout; GlyphBitmap: HBitmap;
29528 GlyphCount: Integer ): PControl;
29530 B: TBitmapInfo;
29531 W, H: Integer;
29532 begin
29533 Result := _NewControl( AParent, 'BUTTON', WS_VISIBLE or WS_CHILD or
29534 WS_TABSTOP or BS_OWNERDRAW, False, @ButtonActions );
29535 Result.fIgnoreDefault := TRUE;
29536 Result.fIsButton := TRUE;
29537 Result.fCommandActions.aAutoSzX := 8;
29538 Result.fCommandActions.aAutoSzY := 8;
29539 //Result.fExStyle := Result.fExStyle and not WS_EX_CONTROLPARENT;
29540 Result.fBitBtnOptions := Options;
29541 Result.fGlyphLayout := Layout;
29542 Result.fGlyphBitmap := GlyphBitmap;
29543 with Result.fBoundsRect do
29544 begin
29545 Bottom := Top + 22;
29546 W := 0; H := 0;
29547 if GlyphBitmap <> 0 then
29548 begin
29549 if bboImageList in Options then
29550 ImageList_GetIconSize( GlyphBitmap, W, H )
29551 else
29552 begin
29553 if GetObject( GlyphBitmap, Sizeof(B), @B ) > 0 then
29554 begin
29555 W := B.bmiHeader.biWidth;
29556 H := B.bmiHeader.biHeight;
29557 if GlyphCount = 0 then
29558 GlyphCount := W div H;
29559 if GlyphCount > 1 then
29560 W := W div GlyphCount;
29561 end;
29562 end;
29563 if W > 0 then
29564 begin
29565 if (Caption = '') or (Layout = glyphOver) then
29566 begin
29567 Right := Left + W;
29568 Result.fCommandActions.aAutoSzX := 0;
29570 else
29571 if Layout in [ glyphLeft, glyphRight ] then
29572 begin
29573 Right := Right + W;
29574 Inc( Result.fCommandActions.aAutoSzX, W );
29575 end;
29576 end;
29577 if H > 0 then
29578 begin
29579 if Layout in [ glyphTop, glyphBottom ] then
29580 begin
29581 Bottom := Bottom + H;
29582 Inc( Result.fCommandActions.aAutoSzY, H );
29584 else
29585 begin
29586 Bottom := Top + H;
29587 Result.fCommandActions.aAutoSzY := 0;
29588 end;
29589 end;
29590 if not ( bboNoBorder in Options ) then
29591 begin
29592 if W > 0 then
29593 begin
29594 Inc( Right, 4 );
29595 if Result.fCommandActions.aAutoSzX > 0 then
29596 Inc( Result.fCommandActions.aAutoSzX, 4 );
29597 end;
29598 if H > 0 then
29599 begin
29600 Inc( Bottom, 4 );
29601 if Result.fCommandActions.aAutoSzY > 0 then
29602 Inc( Result.fCommandActions.aAutoSzY, 4 );
29603 end;
29604 end;
29605 end;
29606 Result.fGlyphWidth := W;
29607 Result.fGlyphHeight := H;
29608 end;
29609 Result.fGlyphCount := GlyphCount;
29610 if AParent <> nil then
29611 AParent.AttachProc( WndProc_DrawItem );
29612 Result.AttachProc( WndProcBitBtn );
29613 //Result.AttachProc( WndProcDoEraseBkgnd );
29614 Result.fTextAlign := taCenter;
29615 Result.Caption := Caption;
29616 {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}
29617 Result.AttachProc( WndProcBtnReturnClick );
29618 {$ENDIF}
29619 end;
29620 {$ENDIF ASM_VERSION}
29621 //[END NewBitBtn]
29623 {$ENDIF USE_CONSTRUCTORS}
29625 //===================== Check box ========================//
29627 {$IFDEF USE_CONSTRUCTORS}
29628 //[function NewCheckbox]
29629 function NewCheckbox( AParent: PControl; const Caption: String ): PControl;
29630 begin
29631 new( Result, CreateCheckbox( AParent, Caption ) );
29632 end;
29633 //[END NewCheckbox]
29634 {$ELSE not_USE_CONSTRUCTORS}
29636 //[FUNCTION NewCheckbox]
29637 {$IFDEF ASM_VERSION}
29638 function NewCheckbox( AParent: PControl; const Caption: String ): PControl;
29640 CALL NewButton
29641 MOV EDX, [EAX].TControl.fBoundsRect.Left
29642 ADD EDX, 72
29643 MOV [EAX].TControl.fBoundsRect.Right, EDX
29644 MOV [EAX].TControl.fStyle, WS_VISIBLE or WS_CHILD or BS_AUTOCHECKBOX or WS_TABSTOP
29645 MOV [EAX].TControl.fCommandActions.aAutoSzX, 24
29646 end;
29647 {$ELSE ASM_VERSION} //Pascal
29648 function NewCheckbox( AParent: PControl; const Caption: String ): PControl;
29649 begin
29650 Result := NewButton( AParent, Caption );
29651 with Result.fBoundsRect do
29652 begin
29653 Right := Left + 72;
29654 end;
29655 Result.fStyle := WS_VISIBLE or WS_CHILD or
29656 BS_AUTOCHECKBOX or WS_TABSTOP;
29657 Result.fCommandActions.aAutoSzX := 24;
29658 end;
29659 {$ENDIF ASM_VERSION}
29660 //[END NewCheckbox]
29662 {$ENDIF USE_CONSTRUCTORS}
29664 //[function NewCheckBox3State]
29665 function NewCheckBox3State( AParent: PControl; const Caption: String ): PControl;
29666 begin
29667 Result := NewCheckbox( AParent, Caption );
29668 Result.fStyle := Result.fStyle and not BS_AUTOCHECKBOX or BS_AUTO3STATE;
29669 end;
29671 //===================== Radiobox ========================//
29673 //[FUNCTION ClickRadio]
29674 {$IFDEF ASM_VERSION}
29675 procedure ClickRadio( Sender:PObj );
29677 MOV ECX, [EAX].TControl.fParent
29678 JECXZ @@exit
29679 PUSH [EAX].TControl.fMenu
29680 PUSH [ECX].TControl.fRadioLast
29681 PUSH [ECX].TControl.fRadio1st
29682 PUSH [ECX].TControl.fHandle
29683 CALL CheckRadioButton
29684 @@exit:
29685 end;
29686 {$ELSE ASM_VERSION} //Pascal
29687 procedure ClickRadio( Sender:PObj );
29688 var Self_:PControl;
29689 begin
29690 Self_ := PControl( Sender );
29691 if Self_.FParent <> nil then
29692 CheckRadioButton( Self_.fParent.fHandle,
29693 Self_.fParent.fRadio1st,
29694 Self_.fParent.fRadioLast,
29695 Self_.fMenu );
29696 end;
29697 {$ENDIF ASM_VERSION}
29698 //[END ClickRadio]
29700 {$IFDEF USE_CONSTRUCTORS}
29701 //[function NewRadiobox]
29702 function NewRadiobox( AParent: PControl; const Caption: String ): PControl;
29703 begin
29704 new( Result, CreateRadiobox( AParent, Caption ) );
29705 end;
29706 //[END NewRadiobox]
29707 {$ELSE not_USE_CONSTRUCTORS}
29709 //[FUNCTION NewRadiobox]
29710 {$IFDEF ASM_VERSION}
29711 function NewRadiobox( AParent: PControl; const Caption: String ): PControl;
29712 const
29713 RadioboxStyles = WS_VISIBLE or WS_CHILD or BS_RADIOBUTTON or
29714 WS_TABSTOP or WS_GROUP or BS_NOTIFY;
29716 PUSH EBX
29717 PUSH EAX
29718 CALL NewCheckbox
29719 XCHG EBX, EAX
29720 MOV [EBX].TControl.fStyle, RadioboxStyles
29721 MOV [EBX].TControl.fControlClick, offset[ClickRadio]
29722 POP ECX
29723 JECXZ @@exit
29724 MOV EDX, [EBX].TControl.fMenu
29725 MOV [ECX].TControl.fRadioLast, EDX
29726 MOV EAX, [ECX].TControl.fRadio1st
29727 TEST EAX, EAX
29728 JNZ @@exit
29729 MOV [ECX].TControl.fRadio1st, EDX
29730 MOV EAX, EBX
29731 CALL TControl.SetRadioChecked
29732 @@exit: XCHG EAX, EBX
29733 POP EBX
29734 end;
29735 {$ELSE ASM_VERSION} //Pascal
29736 function NewRadiobox( AParent: PControl; const Caption: String ): PControl;
29737 begin
29738 Result := NewCheckbox( AParent, Caption );
29739 Result.fStyle := WS_VISIBLE or WS_CHILD or
29740 BS_RADIOBUTTON or WS_TABSTOP or WS_GROUP or BS_NOTIFY;
29741 Result.fControlClick := ClickRadio;
29742 if AParent <> nil then
29743 begin
29744 AParent.fRadioLast := Result.fMenu;
29745 if AParent.fRadio1st = 0 then
29746 begin
29747 AParent.fRadio1st := Result.fMenu;
29748 Result.SetRadioChecked;
29749 end;
29750 end;
29751 end;
29752 {$ENDIF ASM_VERSION}
29753 //[END NewRadiobox]
29755 {$ENDIF USE_CONSTRUCTORS}
29757 //===================== Label ========================//
29759 {$IFNDEF USE_CONSTRUCTORS}
29760 {$IFDEF ASM_VERSION}
29761 const StaticClass: array[0..6]of Char=('S','T','A','T','I','C',#0);
29762 {$ENDIF ASM_VERSION}
29763 {$ENDIF USE_CONSTRUCTORS}
29765 {$IFDEF USE_CONSTRUCTORS}
29766 //[function NewLabel]
29767 function NewLabel( AParent: PControl; const Caption: String ): PControl;
29768 begin
29769 new( Result, CreateLabel( AParent, Caption ) );
29770 end;
29771 //[END NewLabel]
29772 {$ELSE not_USE_CONSTRUCTORS}
29774 //[FUNCTION NewLabel]
29775 {$IFDEF ASM_VERSION}
29776 function NewLabel( AParent: PControl; const Caption: String ): PControl;
29778 PUSH EDX
29780 PUSH 0
29781 PUSH offset[LabelActions]
29782 MOV ECX, WS_VISIBLE or WS_CHILD or SS_LEFTNOWORDWRAP or SS_NOPREFIX or SS_NOTIFY
29783 MOV EDX, offset[StaticClass]
29784 CALL _NewControl
29785 INC [EAX].TControl.fIsStaticControl
29786 INC [EAX].TControl.fSizeRedraw
29787 MOV EDX, [EAX].TControl.fBoundsRect.Top
29788 ADD EDX, 22
29789 MOV [EAX].TControl.fBoundsRect.Bottom, EDX
29790 POP EDX
29791 PUSH EAX
29792 CALL TControl.SetCaption
29793 POP EAX
29794 end;
29795 {$ELSE ASM_VERSION} //Pascal
29796 function NewLabel( AParent: PControl; const Caption: String ): PControl;
29797 begin
29798 Result := _NewControl( AParent, 'STATIC', WS_VISIBLE or WS_CHILD or
29799 SS_LEFTNOWORDWRAP or SS_NOPREFIX or SS_NOTIFY,
29800 False, @LabelActions );
29801 Result.fIsStaticControl := True;
29802 Result.fSizeRedraw := True;
29803 with Result.fBoundsRect do
29804 begin
29805 //Right := Left + 64;
29806 Bottom := Top + 22;
29807 end;
29808 Result.Caption := Caption;
29809 end;
29810 {$ENDIF ASM_VERSION}
29811 //[END NewLabel]
29813 {$ENDIF USE_CONSTRUCTORS}
29815 //===================== word wrap Label ========================//
29817 {$IFDEF USE_CONSTRUCTORS}
29818 //[function NewWordWrapLabel]
29819 function NewWordWrapLabel( AParent: PControl; const Caption: String ): PControl;
29820 begin
29821 new( Result, CreateWordWrapLabel( AParent, Caption ) );
29822 end;
29823 //[END NewWordWrapLabel]
29824 {$ELSE not_USE_CONSTRUCTORS}
29826 //[FUNCTION NewWordWrapLabel]
29827 {$IFDEF ASM_VERSION}
29828 function NewWordWrapLabel( AParent: PControl; const Caption: String ): PControl;
29830 CALL NewLabel
29831 MOV EDX, [EAX].TControl.fBoundsRect.Top
29832 ADD EDX, 44
29833 MOV [EAX].TControl.fBoundsRect.Bottom, EDX
29834 INC [EAX].TControl.fWordWrap
29835 AND byte ptr [EAX].TControl.fStyle, not SS_LEFTNOWORDWRAP
29836 end;
29837 {$ELSE ASM_VERSION} //Pascal
29838 function NewWordWrapLabel( AParent: PControl; const Caption: String ): PControl;
29839 begin
29840 Result := NewLabel( AParent, Caption );
29841 Result.fWordWrap := TRUE;
29842 with Result.fBoundsRect do
29843 begin
29844 Bottom := Top + 44;
29845 end;
29846 Result.fStyle := Result.fStyle and not SS_LEFTNOWORDWRAP;
29847 end;
29848 {$ENDIF ASM_VERSION}
29849 //[END NewWordWrapLabel]
29851 {$ENDIF USE_CONSTRUCTORS}
29853 //===================== Label Effect ========================//
29855 {$IFDEF USE_CONSTRUCTORS}
29856 function NewLabelEffect( AParent: PControl; const Caption: String; ShadowDeep: Integer ): PControl;
29857 begin
29858 new( Result, CreateLabelEffect( AParent, Caption, ShadowDeep ) );
29859 end;
29860 {$ELSE not_USE_CONSTRUCTORS}
29862 //[FUNCTION NewLabelEffect]
29863 {$IFDEF ASM_VERSION}
29864 function NewLabelEffect( AParent: PControl; const Caption: String; ShadowDeep: Integer ): PControl;
29866 PUSH EBX
29868 PUSH ECX
29869 PUSH EDX
29870 XOR EDX, EDX
29871 CALL NewLabel
29872 MOV EBX, EAX
29873 DEC [EBX].TControl.fIsStaticControl
29874 MOV EDX, offset[WndProcLabelEffect]
29875 CALL TControl.AttachProc
29877 //MOV EAX, EBX
29878 //CALL TControl.GetWindowHandle
29880 POP EDX
29881 MOV EAX, EBX
29882 CALL TControl.SetCaption
29884 MOV EDX, offset[WndProcDoEraseBkgnd]
29885 MOV EAX,EBX
29886 CALL TControl.AttachProc
29887 MOV [EBX].TControl.fTextAlign, taCenter
29888 MOV [EBX].TControl.fTextColor, clWindowText
29889 POP [EBX].TControl.fShadowDeep
29890 INC [EBX].TControl.fIgnoreWndCaption
29891 ADD [EBX].TControl.fBoundsRect.Bottom, 40 - 22
29892 MOV [EBX].TControl.fColor2, clNone
29894 XCHG EAX, EBX
29895 POP EBX
29896 end;
29897 {$ELSE ASM_VERSION} //Pascal
29898 function NewLabelEffect( AParent: PControl; const Caption: String; ShadowDeep: Integer ): PControl;
29899 begin
29900 Result := NewLabel( AParent, '' );
29901 Result.fIsStaticControl := False;
29902 Result.AttachProc( WndProcLabelEffect );
29903 //Result.GetWindowHandle;
29904 Result.Caption := Caption;
29905 Result.AttachProc( WndProcDoEraseBkgnd );
29906 Result.fTextAlign := taCenter;
29907 Result.fTextColor := clWindowText;
29908 Result.fShadowDeep := ShadowDeep;
29909 Result.fIgnoreWndCaption := True;
29910 with Result.fBoundsRect do
29911 begin
29912 Bottom := Top + 40;
29913 end;
29914 Result.fColor2 := clNone;
29915 end;
29916 {$ENDIF ASM_VERSION}
29917 //[END NewLabelEffect]
29919 {$ENDIF USE_CONSTRUCTORS}
29921 //===================== Paint box ========================//
29923 {$IFDEF USE_CONSTRUCTORS}
29924 //[function NewPaintbox]
29925 function NewPaintbox( AParent: PControl ): PControl;
29926 begin
29927 new( Result, CreatePaintBox( AParent ) );
29928 end;
29929 {$ELSE not_USE_CONSTRUCTORS}
29931 //[FUNCTION NewPaintbox]
29932 {$IFDEF ASM_VERSION}
29933 function NewPaintbox( AParent: PControl ): PControl;
29935 XOR EDX, EDX
29936 CALL NewLabel
29937 //PUSH EAX
29938 //MOV EDX, offset[WndProcPaintBox]
29939 //CALL TControl.AttachProc
29940 //POP EAX
29941 ADD [EAX].TControl.fBoundsRect.Right, 40-64
29942 ADD [EAX].TControl.fBoundsRect.Bottom, 40-22
29943 end;
29944 {$ELSE ASM_VERSION} //Pascal
29945 function NewPaintbox( AParent: PControl ): PControl;
29946 begin
29947 Result := NewLabel( AParent, '' );
29948 //Result.AttachProc( WndProcPaintBox );
29949 with Result.fBoundsRect do
29950 begin
29951 Right := Left + 40;
29952 Bottom := Top + 40;
29953 end;
29954 end;
29955 {$ENDIF ASM_VERSION}
29956 //[END NewPaintbox]
29958 {$ENDIF USE_CONSTRUCTORS}
29960 {$IFDEF _D2}
29961 //[API SetBrushOrgEx]
29962 function SetBrushOrgEx(DC: HDC; X, Y: Integer; PrevPt: PPoint): BOOL; stdcall;
29963 external gdi32 name 'SetBrushOrgEx';
29964 {$ENDIF}
29966 //[FUNCTION WndProcDoEraseBkgnd]
29967 {$IFDEF ASM_VERSION}
29968 function WndProcDoEraseBkgnd( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
29969 asm // //
29970 CMP word ptr [EDX].TMsg.message, WM_ERASEBKGND
29971 JNE @@ret_false
29972 MOV byte ptr [ECX], 1
29973 PUSH EBX
29974 PUSH EDI
29975 MOV EBX, EAX
29976 MOV EDI, [EDX].TMsg.wParam
29978 CALL TControl.CreateChildWindows
29979 CMP [EBX].TControl.fTransparent, 0
29980 JNE @@exit
29982 PUSH OPAQUE
29983 PUSH EDI
29984 CALL SetBkMode
29985 MOV EAX, [EBX].TControl.fColor
29986 CALL Color2RGB
29987 PUSH EAX
29988 PUSH EDI
29989 CALL SetBkColor
29990 XOR EAX, EAX
29991 PUSH EAX
29992 PUSH EAX
29993 PUSH EAX
29994 PUSH EDI
29995 CALL SetBrushOrgEx
29996 SUB ESP, 16
29997 PUSH ESP
29998 PUSH [EBX].TControl.fHandle
29999 CALL GetClientRect
30000 MOV EAX, EBX
30001 CALL dword ptr[Global_GetCtlBrushHandle]
30002 MOV EDX, ESP
30003 PUSH EAX
30004 PUSH EDX
30005 PUSH EDI
30006 CALL Windows.FillRect
30007 ADD ESP, 16
30008 @@exit: POP EDI
30009 POP EBX
30010 @@ret_false:
30011 XOR EAX, EAX
30012 end;
30013 {$ELSE ASM_VERSION PAS_VERSION}
30014 function WndProcDoEraseBkgnd( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
30015 var DC: HDC;
30016 R: TRect;
30017 begin
30018 Result := FALSE;
30019 if Msg.message = WM_ERASEBKGND then
30020 begin
30021 Self_.CreateChildWindows;
30022 if Self_.Transparent then Exit;
30023 DC := Msg.wParam;
30024 SetBkMode( DC, OPAQUE );
30025 SetBkColor( DC, Color2RGB( Self_.fColor ) );
30026 SetBrushOrgEx( DC, 0, 0, nil );
30027 GetClientRect( Self_.fHandle, R );
30028 Windows.FillRect( DC, R, Global_GetCtlBrushHandle( Self_ ) );
30029 Rslt := 1;
30030 end;
30031 end;
30032 {$ENDIF ASM_VERSION}
30033 //[END WndProcDoEraseBkgnd]
30035 //[function WndProcImageShow]
30036 function WndProcImageShow( Sender: PControl; var Msg: TMsg;
30037 var Rslt: Integer ): Boolean;
30038 var PaintStruct: TPaintStruct;
30039 IL: PImageList;
30040 OldPaintDC: HDC;
30041 begin
30042 Result := FALSE;
30043 if (Msg.message = WM_PAINT) or (Msg.message = WM_PRINT) then
30044 begin
30045 OldPaintDC := Sender.fPaintDC;
30046 Sender.fPaintDC := Msg.wParam;
30047 if Sender.fPaintDC = 0 then
30048 Sender.fPaintDC := BeginPaint( Sender.fHandle, PaintStruct );
30049 //fOnPaint( Self_, fPaintDC );
30050 IL := Sender.ImageListNormal;
30051 if IL <> nil then
30052 begin
30053 IL.Draw( Sender.fCurIndex, Sender.fPaintDC, 0, 0 );
30054 Result := TRUE;
30055 end;
30056 if Msg.wParam = 0 then
30057 EndPaint( Sender.fHandle, PaintStruct );
30058 Sender.fPaintDC := OldPaintDC;
30059 Rslt := 0;
30060 //Result := True;
30061 Exit;
30062 end;
30063 end;
30065 //[function NewImageShow]
30066 function NewImageShow( AParent: PControl; AImgList: PImageList;
30067 ImgIdx: Integer ): PControl;
30068 var W, H: Integer;
30069 begin
30070 Result := NewLabel( AParent, '' );
30071 Result.ImageListNormal := AImgList;
30072 Result.AttachProc( WndProcImageShow );
30073 Result.AttachProc( WndProcDoEraseBkgnd );
30074 W := 32; H := 32;
30075 if AImgList <> nil then
30076 begin
30077 W := AImgList.ImgWidth;
30078 H := AImgList.ImgHeight;
30079 end;
30080 with Result.fBoundsRect do
30081 begin
30082 Right := Left + W;
30083 Bottom := Top + H;
30084 end;
30085 end;
30086 //[END NewImageShow]
30088 //===================== Scrollbar ========================//
30089 const
30090 KSB_INITIALIZE = WM_USER + 10000;
30091 KSB_KEY = $3232;
30093 //[function WndProcScrollBar]
30094 function WndProcScrollBar( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
30095 begin
30096 Result := False;
30097 case Msg.message of
30098 WM_CREATE:
30099 PostMessage(Sender.Handle, KSB_INITIALIZE, KSB_KEY, KSB_KEY);
30101 KSB_INITIALIZE:
30102 if (Msg.wParam = Msg.lParam) and (Msg.wParam = KSB_KEY) then
30103 begin
30104 Sender.SBPageSize := Sender.fSBPageSize;
30105 Sender.SBMinMax := Sender.fSBMinMax;
30106 Sender.SBPosition := Sender.fSBPosition;
30107 end;
30108 end;
30109 end;
30110 //[END WndProcScrollBar]
30112 //[function WndProcScrollBarParent]
30113 function WndProcScrollBarParent( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
30115 Bar: PControl;
30116 SI: TScrollInfo;
30117 NewPos: Integer;
30118 AllowChange: Boolean;
30119 Cmd: Word;
30121 begin
30122 Result := False;
30123 case Msg.message of
30124 WM_HSCROLL, WM_VSCROLL:
30125 if (Msg.lParam <> 0) then begin
30126 Bar := Pointer(GetProp(Msg.lParam, ID_SELF));
30127 if (Bar <> nil) then begin
30128 FillChar(SI, SizeOf(SI), 0);
30129 SI.cbSize := SizeOf(SI);
30130 SI.fMask := SIF_RANGE or SIF_POS or SIF_TRACKPOS or SIF_PAGE;
30131 Bar.SBGetScrollInfo(SI);
30133 Cmd := Msg.wParam and $0000FFFF;
30134 case Cmd of
30135 SB_BOTTOM: NewPos := SI.nMax;
30136 SB_TOP: NewPos := SI.nMin;
30137 SB_LINEDOWN: NewPos := SI.nPos + 1;
30138 SB_LINEUP: NewPos := SI.nPos - 1;
30139 SB_PAGEDOWN: NewPos := SI.nPos + Integer(SI.nPage);
30140 SB_PAGEUP: NewPos := SI.nPos - Integer(SI.nPage);
30141 SB_THUMBTRACK: NewPos := SI.nTrackPos;
30142 else
30143 Exit;
30144 end;
30146 if (NewPos > SI.nMax - Integer(SI.nPage) + 1) then
30147 NewPos := SI.nMax - Integer(SI.nPage) + 1;
30148 if (NewPos < SI.nMin) then
30149 NewPos := SI.nMin;
30151 AllowChange := True;
30152 if Assigned(Bar.OnSBBeforeScroll) then
30153 Bar.OnSBBeforeScroll(Bar, SI.nPos, NewPos, Cmd, AllowChange);
30154 if AllowChange then
30155 SI.nPos := NewPos
30156 else
30157 SI.nTrackPos := SI.nPos;
30158 Bar.fSBPosition := SI.nPos;
30159 Bar.fSBPosition := Bar.SBSetScrollInfo(SI);
30160 if AllowChange and Assigned(Bar.OnSBScroll) then
30161 Bar.OnSBScroll(Bar, Cmd);
30162 end;
30163 end;
30164 end;
30165 end;
30166 //[END WndProcScrollBarParent]
30168 //[function NewScrollBar]
30169 function NewScrollBar( AParent: PControl; BarSide: TScrollerBar ): PControl;
30170 const SBS_Directions: array[ TScrollerBar ] of DWORD = ( SBS_HORZ or SBS_BOTTOMALIGN,
30171 SBS_VERT or SBS_RIGHTALIGN );
30172 begin
30173 Result := _NewCommonControl(
30174 AParent,
30175 'SCROLLBAR',
30176 WS_VISIBLE or WS_CHILD or SBS_Directions[ BarSide ],
30177 False,
30180 Result.DetachProc(WndProcCtrl);
30181 Result.fLookTabKeys := [tkTab];
30182 Result.AttachProc(WndProcScrollBar);
30183 AParent.AttachProc(WndProcScrollBarParent);
30184 end;
30185 //[END NewScrollBar]
30187 //===================== Scrollbox ========================//
30188 //[function WndProcScrollBox]
30189 function WndProcScrollBox( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
30190 var Bar: DWORD;
30191 SI: TScrollInfo;
30192 OldNotifyProc: pointer;
30193 begin
30195 case Msg.message of
30196 WM_HSCROLL: Bar := SB_HORZ;
30197 WM_VSCROLL: Bar := SB_VERT;
30198 WM_SIZE: begin
30199 if Assigned( Sender.fNotifyChild ) then
30200 Sender.fNotifyChild( Sender, nil );
30201 Result := FALSE;
30202 Exit;
30203 end;
30204 else begin
30205 Result := FALSE;
30206 Exit;
30207 end;
30208 end;
30210 SI.cbSize := Sizeof( SI );
30211 SI.fMask := SIF_RANGE or SIF_POS or SIF_PAGE or
30212 {$IFDEF F_P}$10{$ELSE}SIF_TRACKPOS{$ENDIF};
30213 {$IFDEF _D2}
30214 GetScrollInfo( Sender.fHandle, Bar, SI );
30215 {$ELSE}
30216 GetScrollInfo( Sender.fHandle, Bar, SI );
30217 {$ENDIF}
30218 SI.fMask := SIF_POS;
30219 case LoWord( Msg.wParam ) of
30220 SB_BOTTOM: SI.nPos := SI.nMax;
30221 SB_TOP: SI.nPos := SI.nMin;
30222 SB_LINEDOWN: Inc( SI.nPos, Sender.FScrollLineDist[ Bar ] );
30223 SB_LINEUP: Dec( SI.nPos, Sender.FScrollLineDist[ Bar ] );
30224 SB_PAGEDOWN: Inc( SI.nPos, Max( SI.nPage, 1 ) );
30225 SB_PAGEUP: Dec( SI.nPos, Max( SI.nPage, 1 ) );
30226 SB_THUMBTRACK:SI.nPos := SI.nTrackPos;
30227 end;
30228 if SI.nPos > SI.nMax { - Integer( SI.nPage ) } then
30229 SI.nPos := SI.nMax { - Integer( SI.nPage ) };
30230 if SI.nPos < SI.nMin then
30231 SI.nPos := SI.nMin;
30232 SetScrollInfo( Sender.fHandle, Bar, SI, TRUE );
30234 if Assigned( Sender.fScrollChildren ) then
30235 begin
30236 OldNotifyProc := @ Sender.fNotifyChild;
30237 Sender.fNotifyChild := nil;
30238 Sender.fScrollChildren( Sender );
30239 Sender.fNotifyChild := OldNotifyProc;
30240 end;
30242 SetScrollInfo( Sender.fHandle, Bar, SI, TRUE );
30243 Result := FALSE;
30244 end;
30245 //[END WndProcScrollBox]
30247 //[function NewScrollBox]
30248 function NewScrollBox( AParent: PControl; EdgeStyle: TEdgeStyle;
30249 Bars: TScrollerBars ): PControl;
30250 const Edgestyles: array[ TEdgeStyle ] of DWORD = ( WS_DLGFRAME, SS_SUNKEN, 0 );
30251 var SBFlag: Integer;
30252 begin
30253 SBFlag := EdgeStyles[ EdgeStyle ];
30254 if sbHorizontal in Bars then
30255 SBFlag := SBFlag or WS_HSCROLL;
30256 if sbVertical in Bars then
30257 SBFlag := SBFlag or WS_VSCROLL;
30259 Result := _NewControl( AParent, 'ScrollBox', WS_VISIBLE or WS_CHILD or
30260 SBFlag, EdgeStyle = esLowered, nil );
30261 Result.AttachProc( WndProcForm ); //!!!
30262 Result.AttachProc( WndProcScrollBox );
30263 Result.AttachProc( WndProcDoEraseBkgnd );
30264 Result.fIsControl := TRUE;
30265 end;
30266 //[END NewScrollBox]
30268 //[function WndProcNotifyParentAboutResize]
30269 function WndProcNotifyParentAboutResize( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
30270 var P: PControl;
30271 begin
30272 if (Msg.message = WM_SIZE) or (Msg.message = WM_MOVE) or (Msg.message = CM_SHOW) then
30273 begin
30274 P := Sender.Parent;
30275 if P <> nil then
30276 if Assigned( P.fNotifyChild ) then
30277 P.fNotifyChild( P, nil );
30279 else
30280 if Msg.message = WM_SHOWWINDOW then
30281 PostMessage( Sender.fHandle, CM_SHOW, 0, 0 );
30282 Result := FALSE;
30283 end;
30285 //[procedure CalcMinMaxChildren]
30286 procedure CalcMinMaxChildren( Self_: PControl; var SzR: TRect );
30287 var I: Integer;
30288 C: PControl;
30289 R: TRect;
30290 begin
30291 Szr := MakeRect( 0, 0, 0, 0 );
30292 for I := 0 to Self_.fChildren.fCount - 1 do
30293 begin
30294 C := Self_.fChildren.fItems[ I ];
30295 if C.ToBeVisible then
30296 begin
30297 R := C.BoundsRect;
30298 if (SzR.Left = SzR.Right) or (R.Left < SzR.Left) or (R.Right > SzR.Right) then
30299 begin
30300 if SzR.Left = SzR.Right then
30301 begin
30302 SzR.Left := R.Left;
30303 SzR.Right := R.Right;
30305 else
30306 begin
30307 if R.Left < SzR.Left then SzR.Left := R.Left;
30308 if R.Right > SzR.Right then SzR.Right := R.Right;
30309 end;
30310 end;
30311 if (SzR.Top = SzR.Bottom) or (R.Top < SzR.Top) or (R.Bottom > SzR.Bottom) then
30312 begin
30313 if SzR.Top = SzR.Bottom then
30314 begin
30315 SzR.Top := R.Top;
30316 SzR.Bottom := R.Bottom;
30318 else
30319 begin
30320 if R.Top < SzR.Top then SzR.Top := R.Top;
30321 if R.Bottom > SzR.Bottom then SzR.Bottom := R.Bottom;
30322 end;
30323 end;
30324 end;
30325 end;
30326 Dec( SzR.Left, Self_.Border );
30327 Inc( SzR.Right, Self_.Border - 1 );
30328 Dec( SzR.Top, Self_.Border );
30329 Inc( SzR.Bottom, Self_.Border - 1 );
30330 end;
30332 //[procedure NotifyScrollBox]
30333 procedure NotifyScrollBox( Self_, Child: PControl );
30334 var SI: TScrollInfo;
30336 procedure GetSetScrollInfo( SBar: DWORD; WH, R_RightBottom, SzR_LeftTop, SzR_RightBottom: Integer );
30337 var OldPos: Double;
30338 begin
30339 OldPos := 0;
30340 if not GetScrollInfo( Self_.fHandle, SBar, SI ) then
30341 begin
30342 SI.nMin := 0;
30343 SI.nMax := Max( R_RightBottom - 1, SzR_RightBottom - 1 );
30345 else
30346 begin
30347 if SI.nMax > SI.nMin then
30348 begin
30349 OldPos := (SI.nPos - SI.nMin) / (SI.nMax - SI.nMin);
30350 SI.nMin := 0;
30351 SI.nMax := Max( R_RightBottom - 1, SzR_RightBottom - 1 );
30352 if SzR_LeftTop < 0 then
30353 SI.nMax := Max( R_RightBottom - SzR_LeftTop - 1, WH - 1 );
30355 else
30356 begin
30357 SI.nMin := 0;
30358 SI.nMax := Max( R_RightBottom - 1, SzR_RightBottom - 1 );
30359 end;
30360 end;
30361 SI.nPos := SI.nMin + Round( (SI.nMax - SI.nMin) * OldPos );
30362 SI.nPage := R_RightBottom;
30363 SetScrollInfo( Self_.fHandle, SBar, SI, TRUE );
30364 end;
30366 var W, H: Integer;
30367 SzR: TRect;
30368 R: TRect;
30369 begin
30370 if Assigned( Child ) then
30371 begin
30372 Child.AttachProc( WndProcNotifyParentAboutResize );
30373 Exit;
30374 end;
30375 CalcMinMaxChildren( Self_, SzR );
30376 W := SzR.Right - SzR.Left;
30377 H := SzR.Bottom - SzR.Top;
30379 R := Self_.ClientRect;
30380 if (R.Right = 0) or (R.Bottom = 0) then Exit; // for case when form is minimized
30381 SI.cbSize := sizeof( SI );
30382 SI.fMask := SIF_RANGE or SIF_PAGE or SIF_POS;
30384 GetSetScrollInfo( SB_HORZ, W, R.Right, SzR.Left, SzR.Right );
30385 GetSetScrollInfo( SB_VERT, H, R.Bottom, SzR.Top, SzR.Bottom );
30387 end;
30389 //[procedure ScrollChildren]
30390 procedure ScrollChildren( _Self_: PControl );
30391 var SzR, R: TRect;
30392 I, Xpos, Ypos: Integer;
30393 OldNotifyProc: Pointer;
30394 C: PControl;
30395 DeltaX, DeltaY: Integer;
30397 begin
30399 CalcMinMaxChildren( _Self_, SzR );
30400 Xpos := GetScrollPos( _Self_.fHandle, SB_HORZ );
30401 Ypos := GetScrollPos( _Self_.fHandle, SB_VERT );
30403 DeltaX := -Xpos - SzR.Left;
30404 DeltaY := -Ypos - SzR.Top;
30406 if (DeltaX <> 0) or (DeltaY <> 0) then
30407 begin
30409 OldNotifyProc := @ _Self_.fNotifyChild;
30410 _Self_.fNotifyChild := nil;
30412 for I := 0 to _Self_.fChildren.fCount - 1 do
30413 begin
30414 C := _Self_.fChildren.fItems[ I ];
30415 R := C.BoundsRect;
30416 OffsetRect( R, DeltaX, DeltaY );
30417 C.BoundsRect := R;
30418 end;
30420 _Self_.fNotifyChild := OldNotifyProc;
30421 CalcMinMaxChildren( _Self_, R );
30422 if //(SzR.Left <> R.Left) or (SzR.Top <> R.Top) or
30423 //(Szr.Right <> R.Right) or (SzR.Bottom <> R.Bottom)
30424 ((SzR.Right - SzR.Left) <> (R.Right - R.Left)) or
30425 ((SzR.Bottom - SzR.Top) <> (R.Bottom - R.Top))
30426 then
30427 if Assigned( _Self_.fNotifyChild ) then
30428 _Self_.fNotifyChild( _Self_, nil );
30430 end;
30432 end;
30434 //[function NewScrollBoxEx]
30435 function NewScrollBoxEx( AParent: PControl; EdgeStyle: TEdgeStyle ): PControl;
30436 begin
30437 Result := NewScrollBox( AParent, EdgeStyle, [ ] );
30438 Result.fNotifyChild := NotifyScrollBox;
30439 Result.fScrollChildren := ScrollChildren;
30440 Result.FScrollLineDist[ 0 ] := 16;
30441 Result.FScrollLineDist[ 1 ] := 16;
30442 end;
30444 //[function WndProcOnScroll]
30445 function WndProcOnScroll( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
30446 var Bar: TScrollerBar;
30447 begin
30448 Bar := sbHorizontal; //0
30449 if Msg.message = WM_VSCROLL then
30450 Bar := sbVertical
30451 else
30452 if Msg.message <> WM_HSCROLL then
30453 begin
30454 Result := FALSE;
30455 Exit;
30456 end;
30458 if Assigned( Sender.OnScroll ) then
30459 Sender.OnScroll( Sender, Bar, LoWord( Msg.wParam ), HiWord( Msg.wParam ) );
30460 Result := FALSE;
30461 end;
30463 //[procedure TControl.SetOnScroll]
30464 procedure TControl.SetOnScroll(const Value: TOnScroll);
30465 begin
30466 FOnScroll := Value;
30467 AttachProc( @ WndProcOnScroll );
30468 end;
30470 //===================== Groupbox ========================//
30472 {$IFDEF USE_CONSTRUCTORS}
30473 //[function NewGroupbox]
30474 function NewGroupbox( AParent: PControl; const Caption: String ): PControl;
30475 begin
30476 new( Result, CreateGroupbox( AParent, Caption ) );
30477 end;
30478 //[END NewGroupbox]
30479 {$ELSE not_USE_CONSTRUCTORS}
30481 //[FUNCTION NewGroupbox]
30482 {$IFDEF ASM_VERSION}
30483 function NewGroupbox( AParent: PControl; const Caption: String ): PControl;
30485 PUSH EDX
30486 PUSH 0
30487 PUSH offset[ButtonActions]
30488 MOV EDX, offset[ButtonClass]
30489 MOV ECX, WS_VISIBLE or WS_CHILD or BS_GROUPBOX or WS_TABSTOP or WS_CLIPCHILDREN or WS_CLIPSIBLINGS or WS_GROUP
30490 CALL _NewControl
30491 OR [EAX].TControl.fExStyle, WS_EX_CONTROLPARENT
30492 ADD [EAX].TControl.fBoundsRect.Right, 100-64
30493 ADD [EAX].TControl.fBoundsRect.Bottom, 100-22
30494 ADD [EAX].TControl.fClientTop, 22
30495 XOR EDX, EDX
30496 MOV [EAX].TControl.fTabstop, DL
30497 MOV DL, 2
30498 ADD [EAX].TControl.fClientBottom, EDX
30499 ADD [EAX].TControl.fClientLeft, EDX
30500 ADD [EAX].TControl.fClientRight, EDX
30501 POP EDX
30502 PUSH EAX
30503 CALL TControl.SetCaption
30504 POP EAX
30505 PUSH EAX
30506 MOV EDX, offset[WndProcDoEraseBkgnd]
30507 CALL TControl.AttachProc
30508 POP EAX
30509 end;
30510 {$ELSE ASM_VERSION} //Pascal
30511 function NewGroupbox( AParent: PControl; const Caption: String ): PControl;
30512 begin
30513 Result := _NewControl( AParent, 'BUTTON',
30514 WS_CHILD or
30515 WS_CLIPSIBLINGS or
30516 WS_CLIPCHILDREN or
30517 WS_TABSTOP or
30518 WS_VISIBLE or
30519 BS_NOTIFY or
30520 BS_GROUPBOX
30521 or WS_GROUP,
30522 FALSE, @ ButtonActions );
30523 Result.fExStyle := Result.fExStyle or WS_EX_CONTROLPARENT;
30524 Result.Caption := Caption;
30525 with Result.fBoundsRect do
30526 begin
30527 Right := Left + 100;
30528 Bottom := Top + 100;
30529 end;
30530 Result.fClientTop := 22;
30531 Result.fClientBottom := 2;
30532 Result.fClientLeft := 2;
30533 Result.fClientRight := 2;
30534 Result.fTabstop := False;
30535 Result.AttachProc( WndProcDoEraseBkgnd );
30536 end;
30537 {$ENDIF ASM_VERSION}
30538 //[END NewGroupbox]
30540 {$ENDIF USE_CONSTRUCTORS}
30542 //===================== Panel ========================//
30544 {$IFDEF USE_CONSTRUCTORS}
30545 //[function NewPanel]
30546 function NewPanel( AParent: PControl; EdgeStyle: TEdgeStyle ): PControl;
30547 begin
30548 new( Result, CreatePanel( AParent, EdgeStyle ) );
30549 end;
30550 //[END NewPanel]
30551 {$ELSE not_USE_CONSTRUCTORS}
30553 //[FUNCTION NewPanel]
30554 {$IFDEF ASM_VERSION}
30555 function NewPanel( AParent: PControl; EdgeStyle: TEdgeStyle ): PControl;
30557 PUSH EDX
30558 MOV EDX, offset[StaticClass]
30559 MOV ECX, WS_VISIBLE or WS_CHILD or SS_LEFTNOWORDWRAP or SS_NOPREFIX or SS_NOTIFY
30560 PUSH 0
30561 PUSH offset[LabelActions]
30562 CALL _NewControl
30563 ADD [EAX].TControl.fBoundsRect.Right, 100-64
30564 ADD [EAX].TControl.fBoundsRect.Bottom, 100-64
30565 OR byte ptr [EAX].TControl.fExStyle+2, 1
30566 POP ECX
30567 CMP CL, 1
30568 JG @@exit
30569 JE @@sunken
30570 OR byte ptr [EAX].TControl.fStyle+2, $40
30572 @@sunken:
30573 OR byte ptr [EAX].TControl.fStyle+1, $10
30574 @@exit:
30575 end;
30576 {$ELSE ASM_VERSION} //Pascal
30577 function NewPanel( AParent: PControl; EdgeStyle: TEdgeStyle ): PControl;
30578 const Edgestyles: array[ TEdgeStyle ] of DWORD = ( WS_DLGFRAME, SS_SUNKEN, 0 );
30579 begin
30580 Result := _NewControl( AParent, 'STATIC', WS_VISIBLE or WS_CHILD or SS_NOTIFY or
30581 SS_LEFTNOWORDWRAP or SS_NOPREFIX, False, @LabelActions );
30582 with Result.fBoundsRect do
30583 begin
30584 Right := Left + 100;
30585 Bottom := Top + 100;
30586 end;
30587 Result.Style := Result.Style or Edgestyles[ EdgeStyle ];
30588 Result.ExStyle := Result.fExStyle or WS_EX_CONTROLPARENT;
30589 Result.fVerticalAlign := vaTop;
30590 end;
30591 {$ENDIF ASM_VERSION}
30592 //[END NewPanel]
30594 {$ENDIF USE_CONSTRUCTORS}
30596 //===================== Splitter ==============================//
30598 //{$DEFINE USE_ASM_DODRAG}
30600 {$IFNDEF USE_ASM_DODRAG}
30601 {$DEFINE USE_PAS_DODRAG}
30602 {$ENDIF}
30603 {$IFNDEF ASM_VERSION}
30604 {$DEFINE USE_PAS_DODRAG}
30605 {$ENDIF}
30606 {$IFDEF USE_PAS_DODRAG}
30607 //[procedure DoDrag]
30608 procedure DoDrag( Self_: PControl; Cancel: Boolean );
30609 var NewSize1, NewSize2: Integer;
30610 MousePos: TPoint;
30611 R: TRect;
30612 Prev: PControl;
30613 I, M : Integer;
30614 begin
30615 if Self_.fDragging then
30616 begin
30617 I := Self_.fParent.fChildren.IndexOf( Self_ );
30618 Prev := Self_;
30619 if I > 0 then
30620 Prev := Self_.FParent.fChildren.fItems[ I - 1 ];
30621 GetCursorPos( MousePos );
30622 if Cancel then
30623 MousePos := Self_.fSplitStartPos;
30624 M := 1;
30625 if Self_.FAlign in [ caRight, caBottom ] then
30626 M := -1;
30627 if Self_.FAlign in [ caTop, caBottom ] then
30628 begin
30629 NewSize1 := (MousePos.y - Self_.fSplitStartPos.y)* M
30630 + Self_.fSplitStartSize;
30631 NewSize2 := Self_.fParent.ClientHeight - NewSize1
30632 - Self_.fBoundsRect.Bottom + Self_.fBoundsRect.Top
30633 - Self_.fParent.fMargin * 4;
30634 if Self_.fSecondControl <> nil then
30635 begin
30636 NewSize2 := Self_.fSecondControl.fBoundsRect.Bottom
30637 - Self_.fSecondControl.fBoundsRect.Top;
30638 if Self_.fSecondControl.FAlign = caClient then
30639 NewSize2 := Self_.fSplitStartPos2.y
30640 - (MousePos.y - Self_.fSplitStartPos.y)* M
30641 - Self_.fParent.fMargin * 4;
30642 end;
30644 else
30645 begin
30646 NewSize1 := (MousePos.x - Self_.fSplitStartPos.x)* M
30647 + Self_.fSplitStartSize;
30648 NewSize2 := Self_.fParent.ClientWidth - NewSize1
30649 - Self_.fBoundsRect.Right + Self_.fBoundsRect.Left
30650 - Self_.fParent.fMargin * 4;
30651 if Self_.fSecondControl <> nil then
30652 begin
30653 NewSize2 := Self_.fSecondControl.fBoundsRect.Right
30654 - Self_.fSecondControl.fBoundsRect.Left;
30655 if Self_.fSecondControl.FAlign = caClient then
30656 NewSize2 := Self_.fSplitStartPos2.x
30657 - (MousePos.x - Self_.fSplitStartPos.x)* M
30658 - Self_.fParent.Margin * 4;
30659 end;
30660 end;
30661 if {(Self_.fSplitMinSize1 <> 0) and} (NewSize1 < Self_.fSplitMinSize1) then
30662 begin
30663 Dec( NewSize2, Self_.fSplitMinSize1 - NewSize1 );
30664 NewSize1 := Self_.fSplitMinSize1;
30665 end;
30666 if {(Self_.fSplitMinSize2 <> 0) and} (NewSize2 < Self_.fSplitMinSize2) then
30667 begin
30668 Dec( NewSize1, Self_.fSplitMinSize2 - NewSize2 );
30669 NewSize2 := Self_.fSplitMinSize2;
30670 end;
30671 //if Self_.fSplitMinSize1 <> 0 then
30672 if NewSize1 < Self_.fSplitMinSize1 then Exit;
30673 //if Self_.fSplitMinSize2 <> 0 then
30674 if NewSize2 < Self_.fSplitMinSize2 then Exit;
30675 if assigned( Self_.fOnSplit ) then
30676 if not Self_.fOnSplit( Self_, NewSize1, NewSize2 ) then Exit;
30677 R := Prev.BoundsRect;
30678 case Self_.FAlign of
30679 caTop: R.Bottom := R.Top + NewSize1;
30680 caBottom: R.Top := R.Bottom - NewSize1;
30681 caRight: R.Left := R.Right - NewSize1;
30682 else R.Right := R.Left + NewSize1;
30683 end;
30684 Prev.BoundsRect := R;
30685 Global_Align( Self_.fParent );
30686 end;
30687 end;
30688 {$ENDIF}
30690 const
30691 chkLeft=2;
30692 chkTop=4;
30693 chkRight=8;
30694 chkBott=16;
30696 {$DEFINE USE!_ASM_DODRAG}
30698 //[FUNCTION WndProcSplitter]
30699 {$IFDEF ASM_VERSION}
30700 function WndProcSplitter( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
30702 CMP word ptr [EDX].TMsg.message, WM_NCHITTEST
30703 JNE @@noWM_NCHITTEST
30704 PUSH ECX
30705 PUSH [EDX].TMsg.lParam
30706 PUSH [EDX].TMsg.wParam
30707 PUSH [EDX].TMsg.message
30708 PUSH [EAX].TControl.fHandle
30709 CALL DefWindowProc
30710 TEST EAX, EAX
30711 JLE @@htReady
30712 XOR EAX, EAX
30713 INC EAX
30714 @@htReady:
30715 POP ECX
30716 MOV [ECX], EAX
30717 MOV AL, 1
30720 @@noWM_NCHITTEST:
30721 PUSH EBX
30722 XCHG EBX, EAX
30723 CMP word ptr [EDX].TMsg.message, WM_MOUSEMOVE
30724 JNE @@noWM_MOUSEMOVE
30726 PUSH [EBX].TControl.fCursor
30727 CALL Windows.SetCursor
30729 XOR EDX, EDX
30731 {$IFDEF USE_ASM_DODRAG}
30732 CALL @@DoDrag
30733 {$ELSE}
30734 MOV EAX, EBX
30735 CALL DoDrag
30736 {$ENDIF}
30738 POP EBX
30741 {$IFDEF USE_ASM_DODRAG}
30742 @@DoDrag:
30743 PUSHAD
30744 MOVZX EDI, DL // EDI = 1 if Cancel, 0 otherwise
30745 CMP [EBX].TControl.fDragging, 0
30746 JZ @@e_DoDrag
30747 MOV EAX, [EBX].TControl.fParent
30748 MOV EAX, [EAX].TControl.fChildren
30749 PUSH EAX
30750 MOV EDX, EBX
30751 CALL TList.IndexOf
30752 POP EDX // EDX = Self_.fParent.fChildren:PList
30753 MOV EBP, EBX // Prev := Self_;
30754 TEST EAX, EAX
30755 JLE @@noPrev
30756 MOV EDX, [EDX].TList.fItems
30757 MOV EBP, [EDX+EAX*4-4] // Prev = Self_.fParent.fChildren.fItems[I-1]
30758 PUSH EBP // push Prev
30759 @@noPrev:
30760 PUSH EDX
30761 PUSH EDX
30762 PUSH ESP
30763 CALL GetCursorPos
30764 DEC EDI
30765 JNZ @@noCancel
30766 POP EDX
30767 POP EDX
30768 PUSH [EBX].TControl.fSplitStartPos.y
30769 PUSH [EBX].TControl.fSplitStartPos.x
30770 @@noCancel:
30771 OR EDI, -1
30772 MOV CL, [EBX].TControl.fAlign
30773 MOV AL, 1
30774 SHL EAX, CL
30775 {$IFDEF PARANOIA}
30776 DB $A8, chkRight or chkBott
30777 {$ELSE}
30778 TEST AL, chkRight or chkBott //fAlign in [ caRight, caBottom ] ?
30779 {$ENDIF}
30780 JNZ @@mReady
30781 INC EDI
30782 INC EDI
30783 @@mReady:
30784 MOV EDX, [EBX].TControl.fParent
30785 MOV EBP, [EDX].TControl.fMargin
30786 NEG EBP
30787 {$IFDEF PARANOIA}
30788 DB $A8, chkTop or chkBott
30789 {$ELSE}
30790 TEST AL, chkTop or chkBott // fAlign in [ caTop, caBottom ] ?
30791 {$ENDIF}
30792 XCHG EAX, EDX
30793 JZ @@noTopBottom
30795 CALL TControl.GetClientHeight
30796 XCHG EDX, EAX
30798 POP EAX
30799 POP ESI // MousePos.y
30800 MOV EAX, ESI
30801 PUSH EDX // Self_.fParent.ClientHeight
30802 SUB EAX, [EBX].TControl.fSplitStartPos.y
30803 IMUL EAX, EDI
30804 ADD EAX, [EBX].TControl.fSplitStartSize // EAX = NewSize1
30806 POP EDX
30807 SUB EDX, EAX
30808 SUB EDX, [EBX].TControl.fBoundsRect.Bottom
30809 ADD EDX, [EBX].TControl.fBoundsRect.Top
30810 LEA EDX, [EDX+EBP*4]
30812 MOV ECX, [EBX].TControl.fSecondControl
30813 JECXZ @@noSecondControl
30814 MOV EDX, [ECX].TControl.fBoundsRect.Bottom
30815 SUB EDX, [ECX].TControl.fBoundsRect.Top
30816 CMP [ECX].TControl.fAlign, caClient
30817 JNZ @@noSecondControl
30819 PUSH EAX
30820 MOV EAX, [EBX].TControl.fSplitStartPos.y
30821 SUB EAX, ESI
30822 IMUL EAX, EDI
30823 ADD EAX, [EBX].TControl.fSplitStartPos2.y
30824 LEA EDX, [EAX+EBP*4]
30825 POP EAX
30827 @@noSecondControl:
30828 JMP @@newSizesReady
30830 @@noTopBottom:
30831 CALL TControl.GetClientWidth
30832 XCHG EDX, EAX
30834 POP ESI // MousePos.x
30835 POP ECX
30836 MOV EAX, ESI
30837 PUSH EDX // Self_.fParent.ClientWidth
30838 SUB EAX, [EBX].TControl.fSplitStartPos.x
30839 IMUL EAX, EDI
30840 ADD EAX, [EBX].TControl.fSplitStartSize // EAX = NewSize1
30842 POP EDX
30843 SUB EDX, EAX
30844 SUB EDX, [EBX].TControl.fBoundsRect.Right
30845 ADD EDX, [EBX].TControl.fBoundsRect.Left
30846 LEA EDX, [EDX+EBP*4]
30848 MOV ECX, [EBX].TControl.fSecondControl
30849 JECXZ @@newSizesReady
30850 MOV EDX, [ECX].TControl.fBoundsRect.Right
30851 SUB EDX, [ECX].TControl.fBoundsRect.Left
30852 CMP [ECX].TControl.fAlign, caClient
30853 JNZ @@noSecondControl
30855 PUSH EAX
30856 MOV EAX, [EBX].TControl.fSplitStartPos.x
30857 SUB EAX, ESI
30858 IMUL EAX, EDI
30859 ADD EAX, [EBX].TControl.fSplitStartPos2.x
30860 LEA EDX, [EAX+EBP*4]
30861 POP EAX
30863 @@newSizesReady:
30864 MOV ECX, [EBX].TControl.fSplitMinSize1
30865 //JECXZ @@noCheckMinSize1
30866 SUB ECX, EAX
30867 JLE @@noCheckMinSize1
30868 SUB EDX, ECX
30869 ADD EAX, ECX
30871 @@noCheckMinSize1:
30872 MOV ECX, [EBX].TControl.fSplitMinSize2
30873 //JECXZ @@noCheckMinSize2
30874 SUB ECX, EDX
30875 JLE @@noCheckMinSize2
30876 SUB EAX, ECX
30877 ADD EDX, ECX
30879 @@noCheckMinSize2:
30880 MOV ECX, [EBX].TControl.fOnSplit.TMethod.Code
30881 JECXZ @@noOnSplit
30882 PUSHAD
30883 PUSH EDX
30884 MOV ESI, ECX
30885 XCHG ECX, EAX
30886 MOV EDX, EBX
30887 MOV EAX, [EBX].TControl.fOnSplit.TMethod.Data
30888 CALL ESI
30889 TEST AL, AL
30890 POPAD
30891 JZ @@e_DoDrag
30893 @@noOnSplit:
30894 XCHG ESI, EAX // NewSize1 -> ESI
30895 //MOV EDI, EDX // NewSize2 -> EDI
30896 POP EBP
30897 ADD ESP, -16
30898 MOV EAX, EBP
30899 MOV EDX, ESP
30900 CALL TControl.GetBoundsRect
30901 MOVZX ECX, [EBX].TControl.fAlign
30902 LOOP @@noPrev_caLeft
30903 ADD ESI, [ESP].TRect.Left
30904 MOV [ESP].TRect.Right, ESI
30905 @@noPrev_caLeft:
30906 LOOP @@noPrev_caTop
30907 ADD ESI, [ESP].TRect.Top
30908 MOV [ESP].TRect.Bottom, ESI
30909 @@noPrev_caTop:
30910 LOOP @@noPrev_caRight
30911 MOV EAX, [ESP].TRect.Right
30912 SUB EAX, ESI
30913 MOV [ESP].TRect.Left, EAX
30914 @@noPrev_caRight:
30915 LOOP @@noPrev_caBottom
30916 MOV EAX, [ESP].TRect.Bottom
30917 SUB EAX, ESI
30918 MOV [ESP].TRect.Top, EAX
30919 @@noPrev_caBottom:
30920 MOV EAX, EBP
30921 MOV EDX, ESP
30922 CALL TControl.SetBoundsRect
30923 ADD ESP, 16
30924 MOV EAX, [EBX].TControl.fParent
30925 //PUSH EAX
30926 CALL dword ptr[Global_Align]
30927 //POP EAX
30928 //CALL TControl.Update
30930 @@e_DoDrag:
30931 POPAD
30933 {$ENDIF USE_ASM_DODRAG}
30935 @@noWM_MOUSEMOVE:
30936 CMP word ptr [EDX].TMsg.message, WM_LBUTTONDOWN
30937 JNE @@noWM_LBUTTONDOWN
30938 MOV ECX, [EBX].TControl.fParent
30939 TEST ECX, ECX
30940 JZ @@noWM_LBUTTONDOWN
30941 //JECXZ @@noWM_LBUTTONDOWN
30943 MOV EAX, [ECX].TControl.fChildren
30944 PUSH EAX
30945 MOV EDX, EBX
30946 CALL TList.IndexOf
30947 POP ECX
30948 MOV EDX, EBX
30949 TEST EAX, EAX
30950 JLE @@noParent1
30951 MOV ECX, [ECX].TList.fItems
30952 MOV EDX, [ECX+EAX*4-4]
30953 @@noParent1:
30955 MOV CL, [EBX].TControl.fAlign
30956 MOV AL, 1
30957 SHL EAX, CL
30958 {$IFDEF PARANOIA}
30959 DB $A8, chkTop or chkBott
30960 {$ELSE}
30961 TEST AL, chkTop or chkBott // fAlign in [caTop,caBottom] ?
30962 {$ENDIF}
30963 XCHG EAX, EDX
30964 JZ @@no_caTop_caBottom
30965 CALL TControl.GetHeight
30966 JMP @@caTop_caBottom
30967 @@no_caTop_caBottom:
30968 CALL TControl.GetWidth
30969 @@caTop_caBottom:
30970 MOV [EBX].TControl.fSplitStartSize, EAX
30971 MOV ECX, [EBX].TControl.fSecondControl
30972 JECXZ @@noSecondControl1
30973 XCHG EAX, ECX
30974 PUSH EAX
30975 CALL TControl.GetWidth
30976 MOV [EBX].TControl.fSplitStartPos2.x, EAX
30977 POP EAX
30978 CALL TControl.GetHeight
30979 MOV [EBX].TControl.fSplitStartPos2.y, EAX
30980 @@noSecondControl1:
30981 PUSH [EBX].TControl.fHandle
30982 CALL SetCapture
30983 OR [EBX].TControl.fDragging, 1
30984 PUSH 0
30985 PUSH 100
30986 PUSH $7B
30987 PUSH [EBX].TControl.fHandle
30988 CALL SetTimer
30989 LEA EAX, [EBX].TControl.fSplitStartPos
30990 PUSH EAX
30991 CALL GetCursorPos
30992 JMP @@exit
30994 @@noWM_LBUTTONDOWN:
30995 CMP word ptr [EDX].TMsg.message, WM_LBUTTONUP
30996 JNE @@noWM_LBUTTONUP
30997 XOR EDX, EDX
30999 {$IFDEF USE_ASM_DODRAG}
31000 CALL @@DoDrag
31001 {$ELSE}
31002 MOV EAX, EBX
31003 CALL DoDrag
31004 {$ENDIF}
31006 JMP @@killtimer
31008 @@noWM_LBUTTONUP:
31009 CMP word ptr[EDX].TMsg.message, WM_TIMER
31010 JNE @@exit
31011 CMP [EBX].TControl.fDragging, 0
31012 JE @@exit
31013 PUSH VK_ESCAPE
31014 CALL GetAsyncKeyState
31015 TEST EAX, EAX
31016 JGE @@exit
31018 MOV DL, 1
31020 {$IFDEF USE_ASM_DODRAG}
31021 CALL @@DoDrag
31022 {$ELSE}
31023 MOV EAX, EBX
31024 CALL DoDrag
31025 {$ENDIF}
31027 @@killtimer:
31028 MOV [EBX].TControl.fDragging, 0
31029 PUSH $7B
31030 PUSH [EBX].TControl.fHandle
31031 CALL KillTimer
31032 CALL ReleaseCapture
31034 @@exit:
31035 POP EBX
31036 XOR EAX, EAX
31037 end;
31038 {$ELSE ASM_VERSION} //Pascal
31039 function WndProcSplitter( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
31040 var I: Integer;
31041 Prev: PControl;
31043 procedure FinDrag;
31044 begin
31045 KillTimer( Self_.fHandle, $7B );
31046 Self_.fDragging := False;
31047 ReleaseCapture;
31048 end;
31049 begin
31050 case Msg.message of
31051 WM_NCHITTEST:
31052 begin
31053 Rslt := DefWindowProc( Self_.fHandle, Msg.message, Msg.wParam, Msg.lParam );
31054 if Rslt > 0 then
31055 Rslt := HTCLIENT;
31056 Result := True;
31057 Exit;
31058 end;
31059 WM_MOUSEMOVE:
31060 begin
31061 Windows.SetCursor( Self_.fCursor );
31062 DoDrag( Self_, False );
31063 end;
31064 WM_LBUTTONDOWN:
31065 begin
31066 if Self_.fParent <> nil then
31067 begin
31068 I := Self_.fParent.fChildren.IndexOf( Self_ );
31069 Prev := Self_;
31070 if I > 0 then
31071 Prev := Self_.FParent.fChildren.fItems[ I - 1 ];
31072 if Self_.fAlign in [ caTop, caBottom ] then
31073 Self_.fSplitStartSize := Prev.Height
31074 else
31075 Self_.fSplitStartSize := Prev.Width;
31076 if Self_.fSecondControl <> nil then
31077 Self_.fSplitStartPos2 :=
31078 MakePoint( Self_.fSecondControl.Width, Self_.fSecondControl.Height );
31079 SetCapture( Self_.fHandle );
31080 Self_.fDragging := True;
31081 SetTimer( Self_.fHandle, $7B, 100, nil );
31082 GetCursorPos( Self_.fSplitStartPos );
31083 end;
31084 end;
31085 WM_LBUTTONUP:
31086 begin
31087 DoDrag( Self_, False );
31088 FinDrag;
31089 end;
31090 WM_TIMER:
31091 if Self_.fDragging and (GetAsyncKeyState( VK_ESCAPE ) < 0) then
31092 begin
31093 DoDrag( Self_, True );
31094 FinDrag;
31095 end;
31096 end;
31097 Result := False;
31098 end;
31099 {$ENDIF ASM_VERSION}
31100 //[END WndProcSplitter]
31102 //[function NewSplitter]
31103 function NewSplitter( AParent: PControl; MinSizePrev, MinSizeNext: Integer ): PControl;
31104 begin
31105 Result := NewSplitterEx( AParent, MinSizePrev, MinSizeNext, esLowered );
31106 end;
31107 //[END NewSplitter]
31109 {$IFDEF USE_CONSTRUCTORS}
31110 //[function NewSplitterEx]
31111 function NewSplitterEx( AParent: PControl; MinSizePrev, MinSizeNext: Integer;
31112 EdgeStyle: TEdgeStyle ): PControl;
31113 begin
31114 new( Result, CreateSplitter( AParent, MinSizePrev, MinSizeNext, EdgeStyle ) );
31115 end;
31116 //[END NewSplitterEx]
31117 {$ELSE not_USE_CONSTRUCTORS}
31119 //[FUNCTION NewSplitterEx]
31120 {$IFDEF ASM_VERSION}
31121 function NewSplitterEx( AParent: PControl; MinSizePrev, MinSizeNext: Integer;
31122 EdgeStyle: TEdgeStyle ): PControl;
31123 const int_IDC_SIZEWE = integer( IDC_SIZEWE );
31125 PUSH EBX
31126 PUSH EAX // AParent
31127 PUSH ECX // MinSizePrev
31128 PUSH EDX // MinSizeNext
31129 MOV DL, EdgeStyle
31130 CALL NewPanel
31131 XCHG EBX, EAX
31132 POP [EBX].TControl.fSplitMinSize1
31133 POP [EBX].TControl.fSplitMinSize2
31134 XOR EDX, EDX
31135 MOV DL, 4
31136 MOV EAX, [EBX].TControl.fBoundsRect.Left
31137 ADD EAX, EDX
31138 MOV [EBX].TControl.fBoundsRect.Right, EAX
31139 ADD EDX, [EBX].TControl.fBoundsRect.Top
31140 MOV [EBX].TControl.fBoundsRect.Bottom, EDX
31142 POP ECX // ECX = AParent
31143 JECXZ @@noParent2
31144 MOV EAX, [ECX].TControl.fChildren
31145 MOV ECX, [EAX].TList.fCount
31146 CMP ECX, 1
31147 JLE @@noParent2
31149 MOV EAX, [EAX].TList.fItems
31150 MOV EAX, [EAX+ECX*4-8]
31151 MOV CL, [EAX].TControl.fAlign
31152 PUSH ECX
31153 MOV AL, 1
31154 SHL EAX, CL
31155 {$IFDEF PARANOIA}
31156 DB $A8, chkTop or chkBott
31157 {$ELSE}
31158 TEST AL, chkTop or chkBott
31159 {$ENDIF}
31160 MOV EAX, int_IDC_SIZEWE
31161 JZ @@TopBottom
31162 INC EAX
31163 @@TopBottom:
31164 PUSH EAX
31165 PUSH 0
31166 CALL LoadCursor
31167 MOV [EBX].TControl.fCursor, EAX
31168 POP EDX
31169 MOV EAX, EBX
31170 CALL TControl.SetAlign
31172 @@noParent2:
31173 MOV EAX, EBX
31174 MOV EDX, offset[WndProcSplitter]
31175 CALL TControl.AttachProc
31176 XCHG EAX, EBX
31177 POP EBX
31178 end;
31179 {$ELSE ASM_VERSION} //Pascal
31180 function NewSplitterEx( AParent: PControl; MinSizePrev, MinSizeNext: Integer;
31181 EdgeStyle: TEdgeStyle ): PControl;
31182 var PrevCtrl: PControl;
31183 Sz0: Integer;
31184 begin
31185 Result := NewPanel( AParent, EdgeStyle );
31186 Result.fSplitMinSize1 := MinSizePrev;
31187 Result.fSplitMinSize2 := MinSizeNext;
31188 Sz0 := 4;
31189 with Result.fBoundsRect do
31190 begin
31191 Right := Left + Sz0;
31192 Bottom := Top + Sz0;
31193 end;
31194 if AParent <> nil then
31195 begin
31196 if AParent.fChildren.fCount > 1 then
31197 begin
31198 PrevCtrl := AParent.fChildren.fItems[ AParent.fChildren.fCount - 2 ];
31199 case PrevCtrl.FAlign of
31200 caLeft, caRight:
31201 begin
31202 Result.fCursor := LoadCursor( 0, IDC_SIZEWE );
31203 end;
31204 caTop, caBottom:
31205 begin
31206 Result.fCursor := LoadCursor( 0, IDC_SIZENS );
31207 end;
31208 end;
31209 Result.Align := PrevCtrl.FAlign;
31210 end;
31211 end;
31212 Result.AttachProc( WndProcSplitter );
31213 end;
31214 {$ENDIF ASM_VERSION}
31215 //[END NewSplitterEx]
31217 {$ENDIF USE_CONSTRUCTORS}
31219 //===================== MDI client window control =============//
31221 //[procedure DestroyMDIChildren]
31222 procedure DestroyMDIChildren( Form: PControl );
31223 var MDIClient: PControl;
31224 I: Integer;
31225 Ch: PControl;
31226 begin
31227 //Form.fDefWndProc := nil;
31228 MDIClient := Form.fMDIClient;
31229 MDIClient.fMDIDestroying := TRUE;
31230 if MDIClient = nil then Exit;
31231 if MDIClient.fMDIChildren <> nil then
31232 for I := MDIClient.fMDIChildren.Count - 1 downto 0 do
31233 begin
31234 Ch := MDIClient.fMDIChildren.fItems[ I ];
31235 if Ch.fHandle <> 0 then
31236 MDIClient.Perform( WM_MDIDESTROY, Ch.fHandle, 0 );
31237 end;
31238 MDIClient.fMDIChildren.Free;
31239 MDIClient.fMDIChildren := nil;
31240 if Form.fMenu <> 0 then
31241 begin
31242 MDIClient.Perform( WM_MDISETMENU, 0, 0 );
31243 MDIClient.Perform( WM_MDIREFRESHMENU, 0, 0 );
31244 DrawMenuBar( Form.fHandle );
31245 Form.fMenuObj.Free;
31246 Form.fMenuObj := nil;
31247 end;
31248 Form.fMDIClient := nil;
31249 MDIClient.Free;
31250 end;
31252 //[function ProcMDIAccel]
31253 function ProcMDIAccel( Applet: PControl; var Msg: TMsg ): Boolean;
31254 var Form: PControl;
31255 begin
31256 Result := FALSE;
31257 if (Msg.message >= WM_KEYFIRST) and (Msg.message <= WM_KEYLAST) then
31258 begin
31259 Form := Applet.ActiveControl;
31260 if Form <> nil then
31261 begin
31262 if Form.IsMDIChild then
31263 Form := Form.Parent;
31264 Form := Form.ParentForm;
31265 if (Form <> nil) and (Form.MDIClient <> nil) then
31266 Result := TranslateMDISysAccel( Form.MDIClient.fHandle, Msg );
31267 end;
31268 end;
31269 end;
31271 //[function CallDefFrameProc]
31272 function CallDefFrameProc( Wnd: HWnd; Msg: Integer; wParam, lParam: Integer ): Integer;
31273 stdcall;
31274 var Form: PControl;
31275 begin
31276 Form := Pointer( GetProp( Wnd, ID_SELF ) );
31277 if Form <> nil then
31278 Form := Form.ParentForm;
31279 if (Form <> nil) and (Form.fMDIClient <> nil) then
31280 Result := DefFrameProc( Wnd, Form.fMDIClient.fHandle, Msg, wParam, lParam )
31281 else
31282 Result := DefWindowProc( Wnd, Msg, wParam, lParam );
31283 end;
31285 //[function WndFuncMDIClient]
31286 function WndFuncMDIClient( Wnd: HWnd; Msg, wParam, lParam: Integer ): Integer;
31287 stdcall;
31288 var C: PControl;
31289 M: TMsg;
31290 begin
31291 C := Pointer( GetProp( Wnd, ID_SELF ) );
31292 if C <> nil then
31293 begin
31294 M.hwnd := Wnd;
31295 M.message := Msg;
31296 M.wParam := wParam;
31297 M.lParam := lParam;
31298 Result := C.WndProc( M );
31300 else
31301 Result := DefWindowProc( Wnd, Msg, wParam, lParam );
31302 end;
31304 //[function ShowMDIClientEdge]
31305 function ShowMDIClientEdge( MDIClient: PControl ): Boolean;
31306 var ShowEdge: Boolean;
31307 I: Integer;
31308 Ch: PControl;
31309 ExStyle: Integer;
31310 begin
31311 Result := FALSE;
31312 ShowEdge := TRUE;
31313 if MDIClient.fMDIChildren.Count > 0 then
31314 for I := 0 to MDIClient.fMDIChildren.Count-1 do
31315 begin
31316 Ch := MDIClient.fMDIChildren.fItems[ I ];
31317 if IsZoomed( Ch.fHandle ) then
31318 begin
31319 ShowEdge := FALSE;
31320 break;
31321 end;
31322 end;
31323 ExStyle := MDIClient.ExStyle;
31324 if ShowEdge then
31325 if ExStyle and WS_EX_CLIENTEDGE = 0 then
31326 ExStyle := ExStyle or WS_EX_CLIENTEDGE
31327 else
31328 Exit
31329 else if ExStyle and WS_EX_CLIENTEDGE <> 0 then
31330 ExStyle := ExStyle and not WS_EX_CLIENTEDGE
31331 else
31332 Exit;
31333 MDIClient.ExStyle := ExStyle;
31334 Result := TRUE;
31335 end;
31337 //[function WndProcMDIClient]
31338 function WndProcMDIClient( MDIClient: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
31339 {var I: Integer;
31340 Ch: PControl;}
31341 begin
31342 if not MDIClient.fMDIDestroying then
31343 case Msg.message of
31344 $3f:
31345 begin
31346 PostMessage( MDIClient.fHandle, CM_MDIClientShowEdge, 0, 0 );
31347 end;
31348 CM_MDIClientShowEdge:
31349 begin
31350 ShowMDIClientEdge( MDIClient );
31351 end;
31352 WM_NCHITTEST: // not necessary though
31353 begin
31354 Rslt := DefWindowProc( MDIClient.fHandle, WM_NCHITTEST, Msg.wParam, Msg.lParam );
31355 if Rslt = HTCLIENT then Rslt := HTTRANSPARENT;
31356 end;
31357 WM_WINDOWPOSCHANGING:
31358 begin
31359 MDIClient.Perform( WM_SETREDRAW, 0, 0 );
31360 end;
31361 WM_WINDOWPOSCHANGED:
31362 begin
31363 Global_Align( MDIClient.Parent );
31364 MDIClient.Invalidate;
31365 MDIClient.Parent.Invalidate;
31366 MDIClient.Perform( WM_SETREDRAW, 1, 0 );
31367 PostMessage( MDIClient.fHandle, CM_INVALIDATE, 0, 0 );
31368 end;
31369 CM_INVALIDATE:
31370 begin
31371 MDIClient.InvalidateNC( TRUE );
31372 MDIClient.InvalidateEx;
31373 {for I := 0 to MDIClient.fMDIChildren.Count-1 do
31374 begin
31375 Ch := MDIClient.fMDIChildren.fItems[ I ];
31376 Ch.InvalidateEx;
31377 Ch.Perform( WM_NCPAINT, 1, 0 );
31378 end;}
31379 end;
31380 end;
31381 Result := FALSE;
31382 end;
31384 // function added by Thaddy de Koning to fix MDI behaviour
31385 //[function WndProcParentNotifyMouseLDown]
31386 function WndProcParentNotifyMouseLDown( Sender: PControl; var Msg: TMsg;
31387 var Rslt: Integer ): Boolean;
31388 begin
31389 Result := FALSE;
31390 if (Sender.IsMDIChild) and (Msg.message = WM_PARENTNOTIFY) and
31391 (LOWORD(msg.wparam)=WM_LBUTTONDOWN) then
31392 BringWindowToTop( Sender.Handle );
31393 end;
31395 //[function NewMDIClient]
31396 function NewMDIClient( AParent: PControl; WindowMenu: THandle ): PControl;
31397 var F: PControl;
31398 CCS: TClientCreateStruct;
31399 PrntWin: HWnd;
31400 begin
31401 F := nil;
31402 PrntWin := 0;
31403 if AParent <> nil then
31404 begin
31405 F := AParent.ParentForm;
31406 if F <> nil then
31407 begin
31408 F.Add2AutoFreeEx( TObjectMethod( MakeMethod( F, @ DestroyMDIChildren ) ) );
31409 F.GetWindowHandle; // must be created before MDI client creation
31410 F.fDefWndProc := @CallDefFrameProc;
31411 end;
31412 PrntWin := AParent.GetWindowHandle;
31413 end;
31414 Applet.fExMsgProc := ProcMDIAccel;
31415 Result := _NewControl( AParent, 'MDICLIENT',
31416 WS_CHILD or WS_CLIPCHILDREN or WS_VSCROLL or WS_HSCROLL or
31417 WS_VISIBLE or WS_TABSTOP or MDIS_ALLCHILDSTYLES, TRUE, nil );
31418 {Result.fBoundsRect.Right := Result.fBoundsRect.Left + 300;
31419 Result.fBoundsRect.Bottom := Result.fBoundsRect.Top + 200;}
31420 Result.fMDIChildren := NewList;
31421 Result.fExStyle := WS_EX_CLIENTEDGE;
31423 CCS.hWindowMenu := WindowMenu;
31424 CCS.idFirstChild := $FF00;
31425 Result.fHandle := CreateWindowEx( WS_EX_CLIENTEDGE, 'MDICLIENT', nil,
31426 WS_CHILD or WS_CLIPCHILDREN or WS_VSCROLL or WS_HSCROLL or
31427 WS_VISIBLE or WS_TABSTOP,
31428 //or WS_SYSMENU or WS_MINIMIZEBOX or WS_MAXIMIZEBOX,
31429 0, 0, 0, 0, PrntWin, 0, hInstance, @ CCS );
31430 Result.fDefWndProc := Pointer( GetWindowLong( Result.fHandle, GWL_WNDPROC ) );
31431 SetWindowLong( Result.fHandle, GWL_WNDPROC, Integer( @WndFuncMDIClient ) );
31432 SetProp( Result.fHandle, ID_SELF, Integer( Result ) );
31433 if F <> nil then
31434 F.fMDIClient := Result;
31435 Result.AttachProc( WndProcMDIClient );
31436 Result.GetWindowHandle;
31438 Applet.AttachProc( WndProcParentNotifyMouseLDown );
31439 end;
31441 //===================== MDI child window object ==============//
31442 //[function MDIChildFunc]
31443 function MDIChildFunc( Wnd: HWnd; Msg: DWord; wParam, lParam: Integer ): Integer;
31444 stdcall;
31445 var C: PControl;
31446 M: TMsg;
31447 begin
31448 C := Pointer( GetProp( Wnd, ID_SELF ) );
31449 if C <> nil then
31450 begin
31451 M.hwnd := Wnd;
31452 M.message := Msg;
31453 M.wParam := wParam;
31454 M.lParam := lParam;
31455 Result := C.WndProc( M );
31457 else
31458 Result := DefMDIChildProc( Wnd, Msg, wParam, lParam );
31459 end;
31461 //[function Pass2DefMDIChildProc]
31462 function Pass2DefMDIChildProc( Sender_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
31463 begin
31464 Result := FALSE;
31465 if Sender_ = nil then Exit;
31466 if Sender_.Parent = nil then Exit;
31467 if Sender_.Parent.fDestroying then Exit;
31468 if (Msg.message = WM_SYSCOMMAND) or (Msg.message = WM_CHILDACTIVATE) or
31469 (Msg.message = WM_SETFOCUS) or (Msg.message = WM_SIZE) or
31470 (Msg.message = WM_MOVE) or (Msg.message = WM_MENUCHAR) or
31471 (Msg.message = WM_GETMINMAXINFO) {and IsZoomed( Sender_.fHandle ) {and (Msg.hwnd = Sender_.fHandle) { -- doesn't work -- } then
31472 begin
31473 {if Msg.message = WM_GETMINMAXINFO then
31474 Rslt := DefWindowProc( Msg.hwnd, Msg.message, Msg.lParam, Msg.wParam )
31475 else}
31476 Rslt := DefMDIChildProc( Msg.hwnd, Msg.message, Msg.lParam, Msg.wParam );
31477 Result := TRUE;
31478 end;
31479 end;
31481 //[function WndProcMDIChild]
31482 function WndProcMDIChild( MDIChild: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
31483 var ClientWnd: HWnd;
31484 MDIClient: PControl;
31485 MDIForm: PControl;
31486 begin
31487 Result := FALSE;
31488 MDIClient := MDIChild.Parent;
31489 if MDIClient = nil then Exit;
31490 ClientWnd := MDIClient.fHandle;
31491 if ClientWnd = 0 then Exit;
31492 case Msg.message of
31493 WM_DESTROY:
31494 begin
31495 MDIClient.fMDIChildren.Remove( MDIChild );
31496 MDIForm := MDIClient.ParentForm;
31497 if MDIForm <> nil then
31498 if MDIForm.fHandle <> 0 then
31499 DrawMenuBar( MDIForm.fHandle );
31500 MDIChild.Free;
31501 Result := TRUE;
31502 Exit;
31503 end;
31504 end;
31505 if MDIChild.fNotAvailable then
31506 begin
31507 MDIChild.fNotAvailable := FALSE;
31508 MDIChild.Invalidate;
31509 end;
31510 end;
31512 //[procedure CreateMDIChildExt]
31513 procedure CreateMDIChildExt( Sender: PControl );
31514 var F: PControl;
31515 begin
31516 F := Sender.Parent;
31517 if F <> nil then
31518 F := F.ParentForm;
31519 if F <> nil then
31520 DrawMenuBar( F.fHandle );
31521 end;
31523 //[function NewMDIChild]
31524 function NewMDIChild( AParent: PControl; const ACaption: String ): PControl;
31525 var MDIClient: PControl;
31526 begin
31527 Assert( (AParent <> nil) and (AParent.ParentForm <> nil) and
31528 (AParent.ParentForm.fMDIClient <> nil), 'Error creating MDI child' );
31529 MDIClient := AParent.ParentForm.fMDIClient;
31530 Result := NewForm( MDIClient, ACaption );
31531 Result.fIsMDIChild := TRUE;
31532 Result.fMenu := CtlIdCount;
31533 Inc( CtlIdCount );
31534 MDIClient.fMDIChildren.Add( Result );
31535 Result.fExStyle := Result.fExStyle or WS_EX_MDICHILD;
31536 Result.fWndFunc := @ MDIChildFunc;
31537 Result.fDefWndProc := @DefMDIChildProc;
31538 Result.fPass2DefProc := Pass2DefMDIChildProc;
31539 Result.AttachProc( WndProcMDIChild );
31541 Result.SubClassName := 'MDI_chld';
31542 Result.fNotAvailable := TRUE;
31543 Result.fCreateWndExt := CreateMDIChildExt;
31545 end;
31547 //===================== Gradient panel ========================//
31549 {$IFDEF USE_CONSTRUCTORS}
31550 //[function NewGradientPanel]
31551 function NewGradientPanel( AParent: PControl; Color1, Color2: TColor ): PControl;
31552 begin
31553 new( Result, CreateGradientPanel( AParent, Color1, Color2 ) );
31554 end;
31555 //[END NewGradientPanel]
31556 {$ELSE not_USE_CONSTRUCTORS}
31558 //[FUNCTION NewGradientPanel]
31559 {$IFDEF ASM_VERSION}
31560 function NewGradientPanel( AParent: PControl; Color1, Color2: TColor ): PControl;
31562 PUSH ECX
31563 PUSH EDX
31564 XOR EDX, EDX
31565 CALL NewLabel
31566 PUSH EAX
31567 MOV EDX, offset[WndProcGradient]
31568 CALL TControl.AttachProc
31569 POP EAX
31570 POP [EAX].TControl.fColor1
31571 POP [EAX].TControl.fColor2
31572 ADD [EAX].TControl.fBoundsRect.Right, 40-64
31573 ADD [EAX].TControl.fBoundsRect.Bottom, 40 - 22
31574 end;
31575 {$ELSE ASM_VERSION} //Pascal
31576 function NewGradientPanel( AParent: PControl; Color1, Color2: TColor ): PControl;
31577 begin
31578 Result := NewLabel( AParent, '' );
31579 Result.AttachProc( WndProcGradient );
31580 Result.fColor2 := Color2;
31581 Result.fColor1 := Color1;
31582 with Result.fBoundsRect do
31583 begin
31584 Right := Left + 40;
31585 Bottom := Top + 40;
31586 end;
31587 end;
31588 {$ENDIF ASM_VERSION}
31589 //[END NewGradientPanel]
31591 {$ENDIF USE_CONSTRUCTORS}
31593 {$IFDEF USE_CONSTRUCTORS}
31594 //[function NewGradientPanelEx]
31595 function NewGradientPanelEx( AParent: PControl; Color1, Color2: TColor;
31596 Style: TGradientStyle; Layout: TGradientLayout ): PControl;
31597 begin
31598 new( Result, CreateGradientPanelEx( AParent, Color1, Color2,
31599 Style, Layout ) );
31600 end;
31601 //[END NewGradientPanelEx]
31602 {$ELSE not_USE_CONSTRUCTORS}
31604 //[FUNCTION NewGradientPanelEx]
31605 {$IFDEF ASM_VERSION}
31606 function NewGradientPanelEx( AParent: PControl; Color1, Color2: TColor;
31607 Style: TGradientStyle; Layout: TGradientLayout ): PControl;
31609 PUSH ECX
31610 PUSH EDX
31611 XOR EDX, EDX
31612 CALL NewLabel
31613 PUSH EAX
31614 MOV EDX, offset[WndProcGradientEx]
31615 CALL TControl.AttachProc
31616 POP EAX
31617 POP [EAX].TControl.fColor1
31618 POP [EAX].TControl.fColor2
31619 ADD [EAX].TControl.fBoundsRect.Right, 40-100
31620 ADD [EAX].TControl.fBoundsRect.Bottom, 40 - 22
31621 MOV DL, Style
31622 MOV [EAX].TControl.fGradientStyle, DL
31623 MOV DL, Layout
31624 MOV [EAX].TControl.fGradientLayout, DL
31625 end;
31626 {$ELSE ASM_VERSION} //Pascal
31627 function NewGradientPanelEx( AParent: PControl; Color1, Color2: TColor;
31628 Style: TGradientStyle; Layout: TGradientLayout ): PControl;
31629 begin
31630 Result := NewLabel( AParent, '' );
31631 Result.AttachProc( WndProcGradientEx );
31632 Result.fColor2 := Color2;
31633 Result.fColor1 := Color1;
31634 Result.fGradientStyle := Style;
31635 Result.fGradientLayout := Layout;
31636 with Result.fBoundsRect do
31637 begin
31638 Right := Left + 40;
31639 Bottom := Top + 40;
31640 end;
31641 end;
31642 {$ENDIF ASM_VERSION}
31643 //[END NewGradientPanelEx]
31645 {$ENDIF USE_CONSTRUCTORS}
31647 //===================== Edit box ========================//
31649 const Editflags: array [ TEditOption ] of Integer = (
31650 not (ES_AUTOHSCROLL or WS_HSCROLL),
31651 not (es_AutoVScroll or WS_VSCROLL),
31652 es_Lowercase, es_Multiline,
31653 es_NoHideSel, es_OemConvert, es_Password, es_Readonly,
31654 es_UpperCase, es_WantReturn, 0, es_Number );
31656 {$IFDEF USE_CONSTRUCTORS}
31657 //[function NewEditbox]
31658 function NewEditbox( AParent: PControl; Options: TEditOptions ) : PControl;
31659 begin
31660 new( Result, CreateEditbox( AParent, Options ) );
31661 end;
31662 //[END NewEditbox]
31663 {$ELSE not_USE_CONSTRUCTORS}
31665 //[FUNCTION NewEditBox]
31666 {$IFDEF ASM_VERSION}
31667 const EditClass: array[0..4] of Char = ( 'E','D','I','T',#0 );
31668 function NewEditbox( AParent: PControl; Options: TEditOptions ) : PControl;
31669 const int_IDC_IBEAM = integer( IDC_IBEAM );
31670 const WS_flags = integer( WS_VISIBLE or WS_CHILD or WS_TABSTOP or WS_BORDER );
31671 const WS_clear = integer( not(WS_VSCROLL or WS_HSCROLL) );
31673 PUSH EBX
31674 XCHG EBX, EAX // EBX=AParent
31675 PUSH EDX
31676 MOV EAX, ESP
31677 XOR ECX, ECX
31678 MOV CL, 11
31679 MOV EDX, offset [EditFlags]
31680 CALL MakeFlags
31681 XCHG ECX, EAX // ECX = Flags
31682 POP EAX // Options
31683 PUSH EAX
31684 {$IFDEF PARANOIA}
31685 DB $A8, 8
31686 {$ELSE}
31687 TEST AL, 8
31688 {$ENDIF}
31689 JNZ @@1
31690 AND ECX, WS_clear
31691 @@1: OR ECX, WS_flags
31692 PUSH 1
31693 PUSH offset [EditActions]
31694 MOV EDX, offset [EditClass]
31695 XCHG EAX, EBX
31696 CALL _NewControl
31697 XCHG EBX, EAX
31698 { //YS
31699 PUSH int_IDC_IBEAM
31700 PUSH 0
31701 CALL LoadCursor
31702 MOV [EBX].TControl.fCursor, EAX
31704 LEA ECX, [EBX].TControl.fBoundsRect
31705 MOV EDX, [ECX].TRect.Left
31706 ADD EDX, 100
31707 MOV [ECX].TRect.Right, EDX
31708 MOV EDX, [ECX].TRect.Top
31709 ADD EDX, 22
31710 MOV [ECX].TRect.Bottom, EDX
31711 POP EAX // Options
31712 {$IFDEF PARANOIA}
31713 DB $A8, 8
31714 {$ELSE}
31715 TEST AL, 8
31716 {$ENDIF}
31717 MOV DL, $0D
31718 JZ @@2
31719 ADD [ECX].TRect.Right, 100
31720 ADD [ECX].TRect.Bottom, 200 - 22
31721 MOV DL, 1
31722 INC [EBX].TControl.fIgnoreDefault
31723 @@2: //MOV [EBX].TControl.fColor, clWindow
31724 TEST AH, 4
31725 JZ @@3
31726 AND DL, $FE
31727 @@3: MOV [EBX].TControl.fLookTabKeys, DL
31728 XCHG EAX, EBX
31729 POP EBX
31730 end;
31731 {$ELSE ASM_VERSION} //Pascal
31732 function NewEditbox( AParent: PControl; Options: TEditOptions ) : PControl;
31733 var Flags: Integer;
31734 begin
31735 Flags := MakeFlags( @Options, EditFlags );
31736 if not(eoMultiline in Options) then
31737 Flags := Flags and not(WS_HSCROLL or WS_VSCROLL);
31738 Result := _NewControl( AParent, 'EDIT', WS_VISIBLE or WS_CHILD or WS_TABSTOP
31739 or WS_BORDER or Flags, True, @EditActions );
31740 // Result.fCursor := LoadCursor( 0, IDC_IBEAM ); {YS}
31741 with Result.fBoundsRect do
31742 begin
31743 Right := Left + 100;
31744 Bottom := Top + 22;
31745 if eoMultiline in Options then
31746 begin
31747 Right := Right + 100;
31748 Bottom := Top + 200;
31749 Result.fIgnoreDefault := TRUE;
31750 end;
31751 end;
31752 Result.fLookTabKeys := [ tkTab, tkUpDown, tkPageUpPageDn ];
31753 if eoMultiline in Options then
31754 Result.fLookTabKeys := [ tkTab ];
31755 if eoWantTab in Options then
31756 Result.fLookTabKeys := Result.fLookTabKeys - [ tkTab ];
31757 end;
31758 {$ENDIF ASM_VERSION}
31759 //[END NewEditBox]
31761 {$ENDIF USE_CONSTRUCTORS}
31763 //===================== List box ========================//
31765 const ListFlags: array[TListOption] of Integer = (
31766 LBS_DISABLENOScroll, not LBS_ExtendedSel,
31767 LBS_MultiColumn or WS_HSCROLL,
31768 LBS_MultiPLESel,
31769 LBS_NoIntegralHeight, LBS_NoSel, LBS_Sort, LBS_USETabstops,
31770 not LBS_HASSTRINGS, LBS_NODATA, LBS_OWNERDRAWFIXED, LBS_OWNERDRAWVARIABLE );
31772 {$IFDEF USE_CONSTRUCTORS}
31773 //[function NewListbox]
31774 function NewListbox( AParent: PControl; Options: TListOptions ): PControl;
31775 begin
31776 new( Result, CreateListbox( AParent, Options ) );
31777 end;
31778 //[END NewListbox]
31779 {$ELSE not_USE_CONSTRUCTORS}
31781 //[FUNCTION NewListbox]
31782 {$IFDEF ASM_VERSION}
31783 const ListBoxClass : array[ 0..7 ] of Char = ( 'L','I','S','T','B','O','X',#0 );
31784 function NewListbox( AParent: PControl; Options: TListOptions ): PControl;
31786 PUSH EAX
31787 PUSH EDX
31788 MOV EAX, ESP
31789 MOV EDX, offset[ListFlags]
31790 XOR ECX, ECX
31791 MOV CL, 11
31792 CALL MakeFlags
31793 POP EDX
31794 OR EAX, WS_VISIBLE or WS_CHILD or WS_TABSTOP or WS_BORDER or WS_VSCROLL or LBS_NOTIFY
31795 XCHG ECX, EAX
31796 POP EAX
31797 PUSH 1
31798 PUSH offset[ListActions]
31799 MOV EDX, offset[ListBoxClass]
31800 CALL _NewControl
31801 ADD [EAX].TControl.fBoundsRect.Right, 100
31802 ADD [EAX].TControl.fBoundsRect.Bottom, 200-64
31803 MOV [EAX].TControl.fColor, clWindow
31804 MOV [EAX].TControl.fLookTabKeys, 3
31805 end;
31806 {$ELSE ASM_VERSION} //Pascal
31807 function NewListbox( AParent: PControl; Options: TListOptions ): PControl;
31808 var Flags: Integer;
31809 begin
31810 Flags := MakeFlags( @Options, ListFlags );
31811 Result := _NewControl( AParent, 'LISTBOX', WS_VISIBLE or WS_CHILD or WS_TABSTOP
31812 or WS_BORDER or WS_VSCROLL
31813 or LBS_NOTIFY or Flags, True, @ListActions );
31814 with Result.fBoundsRect do
31815 begin
31816 Right := Right + 100;
31817 Bottom := Top + 200;
31818 end;
31819 Result.fColor := clWindow;
31820 Result.fLookTabKeys := [ tkTab, tkLeftRight ];
31821 end;
31822 {$ENDIF ASM_VERSION}
31823 //[END NewListbox]
31825 {$ENDIF USE_CONSTRUCTORS}
31827 //===================== Combo box ========================//
31829 //[FUNCTION ComboboxDropDown]
31830 {$IFNDEF USE_DROPDOWNCOUNT}
31831 {$IFDEF ASM_VERSION}
31832 procedure ComboboxDropDown( Sender: PObj );
31834 PUSH EBX
31835 PUSH ESI
31836 MOV EBX, EAX
31837 CALL TControl.GetItemsCount
31838 CMP EAX, 1
31839 JGE @@1
31840 XOR EAX, EAX
31841 INC EAX
31842 @@1: CMP EAX, 8
31843 JLE @@2
31844 XOR EAX, EAX
31845 MOV AL, 8
31846 @@2: XOR ESI, ESI
31847 PUSH SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_NOREDRAW or SWP_SHOWWINDOW
31848 PUSH ESI
31849 PUSH ESI
31850 PUSH SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_NOREDRAW or SWP_HIDEWINDOW
31851 PUSH EAX
31852 MOV EAX, EBX
31853 CALL TControl.GetHeight
31854 POP ECX
31855 INC ECX
31856 IMUL ECX
31857 INC EAX
31858 INC EAX
31859 PUSH EAX
31860 MOV EAX, EBX
31861 CALL TControl.GetWidth
31862 PUSH EAX
31863 INC ESI
31864 @@3: XOR EDX, EDX
31865 PUSH EDX
31866 PUSH EDX
31867 PUSH EDX
31868 PUSH [EBX].TControl.fHandle
31869 CALL SetWindowPos
31870 DEC ESI
31871 JZ @@3
31872 MOV ECX, [EBX].TControl.fOnDropDown.TMethod.Code
31873 JECXZ @@exit
31874 MOV EAX, [EBX].TControl.fOnDropDown.TMethod.Data
31875 MOV EDX, EBX
31876 CALL ECX
31877 @@exit: POP ESI
31878 POP EBX
31879 end;
31880 {$ELSE ASM_VERSION} //Pascal
31881 procedure ComboboxDropDown( Sender: PObj );
31883 CB: PControl;
31884 IC: Integer;
31885 begin
31886 CB := PControl( Sender );
31887 IC := CB.Count;
31888 if IC > 8 then IC := 8;
31889 if IC < 1 then IC := 1;
31891 SetWindowPos( CB.Handle, 0, 0, 0, CB.Width, CB.Height * (IC + 1) + 2,
31892 SWP_NOMOVE + SWP_NOZORDER + SWP_NOACTIVATE + SWP_NOREDRAW +
31893 SWP_HIDEWINDOW);
31895 SetWindowPos( CB.Handle, 0, 0, 0, 0, 0, SWP_NOMOVE + SWP_NOSIZE
31896 + SWP_NOZORDER + SWP_NOACTIVATE
31897 + SWP_NOREDRAW + SWP_SHOWWINDOW);
31899 if assigned( CB.fOnDropDown ) then
31900 CB.fOnDropDown( CB );
31902 end;
31903 {$ELSE newcode}
31904 {procedure ComboboxDropDown( Sender: PObj );
31906 CB: PControl;
31907 Count: Integer;
31908 DropDownCount: Integer;
31909 ItemHeight: Integer;
31910 begin
31911 CB := PControl(Sender);
31913 Count := CB.Count;
31914 DropDownCount := CB.DropDownCount;
31915 DropDownCount := 8;
31916 if (Count > DropDownCount) then
31917 Count := DropDownCount;
31918 if (Count < 1) then
31919 Count := 1;
31920 ItemHeight := CB.Perform(CB_GETITEMHEIGHT, 0, 0);
31921 SetWindowPos(
31922 CB.Handle, 0, 0, 0, CB.Width, ItemHeight * Count + CB.Height + 2,
31923 SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_NOREDRAW or SWP_HIDEWINDOW);
31924 SetWindowPos(
31925 CB.Handle, 0, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER or
31926 SWP_NOACTIVATE or SWP_NOREDRAW or SWP_SHOWWINDOW);
31928 if Assigned(CB.fOnDropDown) then
31929 CB.fOnDropDown(CB);
31930 end;}
31931 {$ENDIF USE_DROPDOWNCOUNT}
31932 {$ENDIF ASM_VERSION}
31933 //[END ComboboxDropDown]
31935 //[function WndFuncCombo]
31936 function WndFuncCombo( W: HWnd; Msg: Cardinal; wParam, lParam: Integer )
31937 : Integer; stdcall;
31938 var Combo, Form: PControl;
31939 ParentWnd : HWnd;
31940 MsgStruct: TMsg;
31941 //********************************************************** Added By M.Gerasimov
31943 PrevProc:Pointer;
31945 //********************************************************** Added By M.Gerasimov
31946 begin
31947 Combo := nil;
31949 ParentWnd := GetParent( W );
31950 if ParentWnd <> 0 then
31951 Combo := Pointer( GetProp( ParentWnd, ID_SELF ) );
31953 if Combo <> nil then
31954 begin
31955 MsgStruct.hwnd := Combo.fHandle;
31956 MsgStruct.message := Msg;
31957 MsgStruct.wParam := wParam;
31958 MsgStruct.lParam := lParam;
31959 Form := Combo.ParentForm;
31960 if fGlobalProcKeybd( Combo, MsgStruct, Result ) then Exit;
31961 if W <> Combo.FHandle then
31962 begin
31963 if Assigned( Applet ) and Assigned( Applet.OnMessage ) then
31964 if Applet.OnMessage( MsgStruct, Result ) then Exit;
31965 if (Applet <> Form) and (Form <> nil) then
31966 if Assigned( Form.OnMessage ) then
31967 if Form.OnMessage( MsgStruct, Result ) then Exit;
31968 end;
31969 if //(GetFocus = W) and
31970 (Msg = WM_KEYDOWN) or (Msg = WM_KEYUP) or (Msg = WM_CHAR) then
31971 begin
31972 Result := 0;
31973 if (wParam = VK_TAB) then
31974 begin
31975 case Msg of
31976 WM_KEYDOWN:
31977 if Assigned( Combo.fGotoControl ) and
31978 Combo.fGotoControl( Combo, wParam, FALSE ) then Exit;
31979 else Exit;
31980 end;
31982 else
31983 if (Msg = WM_CHAR) and ((wParam = VK_ESCAPE) or (wParam = VK_RETURN)) then
31984 begin
31985 if Combo.Perform( CB_GETDROPPEDSTATE, 0, 0 ) <> 0 then
31986 begin
31987 Combo.Perform( CB_SHOWDROPDOWN, 0, 0 );
31988 if wParam = VK_ESCAPE then
31989 Combo.Perform( CB_SETCURSEL, Combo.fCurIdxAtDrop, 0 );
31990 Combo.fWndProcKeybd( Combo, MsgStruct, Result );
31991 Exit;
31993 {$IFDEF ESC_CLOSE_DIALOGS}
31994 //---------------------------------Babenko Alexey--------------------------
31995 else
31996 if (wparam = VK_ESCAPE) then
31997 if (combo.ParentForm.ExStyle and WS_EX_DLGMODALFRAME) <> 0 then begin
31998 SendMessage(combo.ParentForm.Handle, WM_CLOSE, 0, 0);
31999 exit;
32000 end;
32001 //---------------------------------Babenko Alexey--------------------------
32002 {$ENDIF}
32003 end;
32004 Combo.fWndProcKeybd( Combo, MsgStruct, Result );
32006 else
32007 if Msg = WM_SETFOCUS then
32008 begin
32009 if Form <> nil then Form.fCurrentControl := Combo;
32010 end;
32011 MsgStruct.hwnd := W;
32012 //********************************************************** Added By M.Gerasimov
32014 PrevProc:=Pointer(GetProp( W, ID_PREVPROC ));
32015 if PrevProc <> Nil then
32016 Result := CallWindowProc( PrevProc , W, Msg, wParam, lParam )
32017 else
32018 Result:=0;
32020 //********************************************************** Added By M.Gerasimov
32021 // Result := CallWindowProc( //Combo.fPrevWndProc
32022 // Pointer( GetProp( W, 'PREV_PROC' ) )
32023 // , W, Msg, wParam, lParam );
32024 //**********************************************************
32026 else
32027 Result := DefWindowProc( W, Msg, wParam, lParam );
32028 end;
32030 //[PROCEDURE CreateComboboxWnd]
32031 {$IFDEF ASM_VERSION}
32032 procedure CreateComboboxWnd( Combo: PControl );
32033 //********************************************************** Remarked By M.Gerasimov
32034 //const PrevProcStr: PChar = 'PREV_PROC';
32035 //********************************************************** Remarked By M.Gerasimov
32037 PUSH EDI
32038 PUSH EBX
32039 XCHG EBX, EAX
32040 PUSH GW_CHILD
32041 PUSH [EBX].TControl.fHandle
32042 //XOR EDI, EDI
32043 @@getwindow:
32044 CALL GetWindow
32045 TEST EAX, EAX
32046 JZ @@fin
32047 {TEST EDI, EDI
32048 XCHG EDI, EAX
32049 JZ @@2getnext}
32050 PUSH offset[WndFuncCombo]
32051 PUSH GWL_WNDPROC
32052 PUSH EAX
32053 XCHG EDI, EAX
32054 CALL SetWindowLong
32055 PUSH EAX
32056 //********************************************* By M.Gerasimov
32057 // PUSH [PrevProcStr]
32058 //************************************************************
32059 PUSH offset [ID_PREVPROC] //
32060 //************************************************************
32061 PUSH EDI
32062 CALL SetProp
32063 @@2getnext:
32064 PUSH GW_HWNDNEXT
32065 PUSH EDI
32066 JMP @@getwindow
32067 @@fin: POP EBX
32068 POP EDI
32069 end;
32070 {$ELSE ASM_VERSION} //Pascal
32071 procedure CreateComboboxWnd( Combo: PControl );
32072 var W : HWND;
32073 PrevProc: DWORD;
32074 begin
32075 W := GetWindow( Combo.fHandle, GW_CHILD );
32076 {if W <> 0 then
32077 W := GetWindow( W, GW_HWNDNEXT );}
32078 while W <> 0 do
32079 begin
32080 PrevProc :=
32081 SetWindowLong( W, GWL_WNDPROC, Longint( @WndFuncCombo ) );
32082 //********************************************* By M.Gerasimov
32083 // SetProp( W, 'PREV_PROC', PrevProc );
32084 //************************************************************
32085 SetProp( W, ID_PREVPROC, PrevProc ); //
32086 //************************************************************
32087 W := GetWindow( W, GW_HWNDNEXT );
32088 end;
32089 end;
32090 {$ENDIF ASM_VERSION}
32091 //[END CreateComboboxWnd]
32093 //[procedure RemoveChldPrevProc]
32094 procedure RemoveChldPrevProc( fHandle: HWnd );
32095 var Chld: HWnd;
32096 begin
32097 Chld := GetWindow( fHandle, GW_CHILD );
32098 while Chld <> 0 do
32099 begin
32100 if GetProp( Chld, ID_PREVPROC ) <> 0 then
32101 RemoveProp(Chld, ID_PREVPROC);
32102 Chld := GetWindow( Chld, GW_HWNDNEXT );
32103 end;
32104 end;
32106 //[function WndProcCombo]
32107 function WndProcCombo( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
32108 begin
32109 Result := FALSE;
32110 if (Msg.message >= WM_CTLCOLORMSGBOX) and (Msg.message <= WM_CTLCOLORSTATIC) then
32111 begin
32112 Rslt := Sender.Perform( Msg.message + CN_BASE, Msg.wParam, Msg.lParam );
32113 Result := TRUE;
32115 else
32116 if //(Msg.message = CN_CTLCOLOREDIT)
32117 (Msg.message >= CN_CTLCOLORMSGBOX) and (Msg.message <= CN_CTLCOLORSTATIC)
32118 {and not AppletTerminated} then
32119 begin
32120 if Sender.fTransparent then
32121 case Msg.message of
32122 CN_CTLCOLORLISTBOX:
32123 begin
32124 SetBkMode( Msg.wParam, Windows.OPAQUE );
32125 SetBkColor(Msg.WParam, Color2RGB( Sender.fColor ) );
32126 Rslt := Global_GetCtlBrushHandle( Sender );
32127 Result := TRUE;
32128 end;
32129 //********************************************************** Added By M.Gerasimov
32131 WM_DESTROY:
32132 RemoveChldPrevProc( Sender.Handle );
32134 //********************************************************** Added By M.Gerasimov
32135 else
32136 if not Sender.DblBufTopParent.fDblBufPainting then
32137 Sender.Invalidate;
32138 end;
32139 //Result := FALSE;
32141 else
32142 if Msg.message = CM_COMMAND then
32143 begin
32144 case HiWord( Msg.wParam ) of
32145 CBN_DROPDOWN:
32146 begin
32147 Sender.fDropped := True;
32148 Sender.fCurIdxAtDrop := Sender.CurIndex;
32149 Sender.fDropDownProc( Sender );
32150 end;
32151 CBN_CLOSEUP:
32152 begin
32153 Sender.fDropped := False;
32154 if Assigned( Sender.fOnCloseUp ) then Sender.fOnCloseUp( Sender );
32155 end;
32156 CBN_SELCHANGE:
32157 begin
32158 PostMessage( Sender.fHandle, CM_COMMAND, CM_CBN_SELCHANGE shl 16, 0 );
32159 end;
32160 end;
32161 end;
32162 end;
32164 const ComboFlags: array[ TComboOption ] of Integer = (
32165 CBS_DROPDOWNLIST, not CBS_AUTOHScroll,
32166 CBS_DISABLENOSCROLL, CBS_LowerCase, CBS_NoIntegralHeight,
32167 CBS_OemConvert, CBS_Sort, CBS_UpperCase,
32168 CBS_OWNERDRAWFIXED, CBS_OWNERDRAWVARIABLE, CBS_SIMPLE );
32170 {$IFDEF USE_CONSTRUCTORS}
32171 //[function NewCombobox]
32172 function NewCombobox( AParent: PControl; Options: TComboOptions ): PControl;
32173 begin
32174 new( Result, CreateCombobox( AParent, Options ) );
32175 end;
32176 {$ELSE not_USE_CONSTRUCTORS}
32178 //[FUNCTION NewCombobox]
32179 {$IFDEF ASM_VERSION}
32180 const ComboboxClass: array[0..8] of Char = ('C','O','M','B','O','B','O','X',#0 );
32181 function NewCombobox( AParent: PControl; Options: TComboOptions ): PControl;
32183 PUSH EDX
32184 PUSH EAX
32185 PUSH EDX
32186 MOV EAX, ESP
32187 MOV EDX, offset[ComboFlags]
32188 XOR ECX, ECX
32189 MOV CL, 10
32190 CALL MakeFlags
32191 POP EDX
32192 XCHG ECX, EAX
32193 POP EAX
32194 PUSH 1
32195 PUSH offset[ComboActions]
32196 MOV EDX, offset[ComboboxClass]
32197 OR ECX, WS_VISIBLE or WS_CHILD or WS_VSCROLL or CBS_HASSTRINGS or WS_TABSTOP
32198 TEST ECX, CBS_SIMPLE
32199 JNZ @@O
32200 OR ECX, CBS_DROPDOWN
32201 @@O:
32202 CALL _NewControl
32203 MOV [EAX].TControl.fCreateWndExt, offset[CreateComboboxWnd]
32204 MOV [EAX].TControl.fDropDownProc, offset[ComboboxDropDown]
32205 OR byte ptr [EAX].TControl.fClsStyle, CS_DBLCLKS
32206 ADD [EAX].TControl.fBoundsRect.Right, 100-64
32207 ADD [EAX].TControl.fBoundsRect.Bottom, 22-64
32208 //MOV [EAX].TControl.fColor, clWindow
32209 MOV CL, 1
32210 POP EDX
32211 TEST DL, 1
32212 JZ @@exit
32213 MOV CL, 3
32214 @@exit:
32215 MOV [EAX].TControl.fLookTabKeys, CL
32216 PUSH EAX
32217 MOV EDX, offset[ WndProcCombo ]
32218 CALL TControl.AttachProc
32219 POP EAX
32220 end;
32221 {$ELSE ASM_VERSION} //Pascal
32222 function NewCombobox( AParent: PControl; Options: TComboOptions ): PControl;
32223 var Flags: Integer;
32224 begin
32225 Flags := MakeFlags( @Options, ComboFlags );
32226 if not LongBool( Flags and CBS_SIMPLE ) then
32227 Flags := Flags or CBS_DROPDOWN;
32228 Result := _NewControl( AParent, 'COMBOBOX',
32229 WS_VISIBLE
32230 or WS_CHILD
32231 or WS_VSCROLL
32232 or CBS_HASSTRINGS or WS_TABSTOP
32233 or Flags
32234 , True, @ComboActions );
32235 //Result.fCannotDoubleBuf := TRUE;
32236 Result.fCreateWndExt := CreateComboboxWnd;
32237 Result.fDropDownProc := ComboboxDropDown;
32238 Result.fClsStyle := Result.fClsStyle or CS_DBLCLKS;
32239 with Result.fBoundsRect do
32240 begin
32241 Right := Left + 100;
32242 Bottom := Top + 22;
32243 end;
32244 Result.fLookTabKeys := [ tkTab ];
32245 if coReadOnly in Options then
32246 Result.fLookTabKeys := [ tkTab, tkLeftRight ];
32247 Result.AttachProc( @ WndProcCombo );
32248 {$IFDEF USE_DROPDOWNCOUNT}
32249 Result.DropDownCount := 8;
32250 {$ENDIF}
32251 end;
32252 {$ENDIF ASM_VERSION}
32253 //[END NewCombobox]
32255 {$ENDIF USE_CONSTRUCTORS}
32257 //[FUNCTION WndProcResiz]
32258 {$IFDEF ASM_VERSION}
32259 function WndProcResize(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
32261 PUSH ESI
32262 CMP word ptr [EDX].TMsg.message, WM_SIZE
32263 JNZ @@exit
32265 MOV ESI, [EAX].TControl.fChildren
32266 MOV ECX, [ESI].TList.fCount
32267 JECXZ @@exit
32268 MOV ESI, [ESI].TList.fItems
32269 @@loo: PUSH ECX
32270 LODSD
32271 PUSH EAX
32272 PUSH EAX
32273 PUSH CM_SIZE
32274 PUSH EAX
32275 CALL TControl.Perform
32276 POP ECX
32277 LOOP @@loo
32279 @@exit: XOR EAX, EAX
32280 POP ESI
32281 end;
32282 {$ELSE ASM_VERSION} //Pascal
32283 function WndProcResize(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
32284 var I: Integer;
32285 C: PControl;
32286 begin
32287 if Msg.message = WM_SIZE then
32288 begin
32289 for I:= 0 to Self_.fChildren.fCount - 1 do
32290 begin
32291 C := Self_.fChildren.fItems[ I ];
32292 C.Perform( CM_SIZE, 0, 0 );
32293 end;
32294 end;
32295 Result := False; // don't stop further processing
32296 end;
32297 {$ENDIF ASM_VERSION}
32298 //[END WndProcResiz]
32300 //[FUNCTION WndProcParentResize]
32301 {$IFDEF ASM_VERSION}
32302 function WndProcParentResize( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
32304 CMP word ptr [EDX].TMsg.message, CM_SIZE
32305 JNZ @@exit
32306 PUSH 0
32307 PUSH 0
32308 PUSH WM_SIZE
32309 PUSH EAX
32310 CALL TControl.Perform
32311 @@exit: XOR EAX, EAX
32312 end;
32313 {$ELSE ASM_VERSION} //Pascal
32314 function WndProcParentResize(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
32315 begin
32316 Result := False;
32317 case Msg.message of
32318 CM_SIZE:
32319 begin
32320 Self_.Perform( WM_SIZE, 0, 0 );
32321 end;
32322 end;
32323 end;
32324 {$ENDIF ASM_VERSION}
32325 //[END WndProcParentResize]
32327 //[procedure InitCommonControlCommonNotify]
32328 procedure InitCommonControlCommonNotify( Ctrl: PControl );
32329 var AParent: PControl;
32330 begin
32331 Ctrl.fIsCommonControl := True;
32332 AParent := Ctrl.Parent;
32333 if AParent <> nil then
32334 begin
32335 Ctrl.AttachProc( WndProcCommonNotify );
32336 AParent.AttachProc( WndProcNotify );
32337 end;
32338 end;
32340 //[procedure InitCommonControlSizeNotify]
32341 procedure InitCommonControlSizeNotify( Ctrl: PControl );
32342 var AParent: PControl;
32343 begin
32344 AParent := Ctrl.Parent;
32345 if AParent <> nil then
32346 begin
32347 Ctrl.AttachProc( WndProcParentResize );
32348 AParent.AttachProc( WndProcResize );
32349 end;
32350 end;
32352 //[function _NewCommonControl]
32353 function _NewCommonControl( AParent: PControl; ClassName: PChar; Style: DWORD;
32354 Ctl3D: Boolean; Actions: PCommandActions ): PControl;
32355 begin
32356 {*************} DoInitCommonControls( ICC_WIN95_CLASSES );
32357 Result := _NewControl( AParent, ClassName, Style, Ctl3D, Actions );
32358 //InitCommonControlSizeNotify( Result );
32359 InitCommonControlCommonNotify( Result );
32360 end;
32362 //==================== Progress bar ======================//
32364 {$IFDEF USE_CONSTRUCTORS}
32365 //[function NewProgressbar]
32366 function NewProgressbar( AParent: PControl ): PControl;
32367 begin
32368 new( Result, CreateProgressbar( AParent ) );
32369 end;
32370 //[END NewProgressbar]
32371 {$ELSE not_USE_CONSTRUCTORS}
32373 //[FUNCTION NewProgressbar]
32374 {$IFDEF ASM_VERSION}
32375 function NewProgressbar( AParent: PControl ): PControl;
32377 PUSH 1
32378 PUSH 0
32379 MOV EDX, offset[Progress_class]
32380 MOV ECX, WS_CHILD or WS_VISIBLE
32381 CALL _NewCommonControl
32382 LEA EDX, [EAX].TControl.fBoundsRect
32383 MOV ECX, [EDX].TRect.Left
32384 ADD ECX, 300
32385 MOV [EDX].TRect.Right, ECX
32386 MOV ECX, [EDX].TRect.Top
32387 ADD ECX, 20
32388 MOV [EDX].TRect.Bottom, ECX
32389 XOR EDX, EDX
32390 MOV [EAX].TControl.fMenu, EDX
32391 MOV [EAX].TControl.fTextColor, clHighlight
32392 MOV [EAX].TControl.fCommandActions.aSetBkColor, PBM_SETBKCOLOR
32393 end;
32394 {$ELSE ASM_VERSION} //Pascal
32395 function NewProgressbar( AParent: PControl ): PControl;
32396 begin
32397 Result := _NewCommonControl( AParent, PROGRESS_CLASS,
32398 WS_CHILD or WS_VISIBLE, True, nil );
32399 with Result.fBoundsRect do
32400 begin
32401 Right := Left + 300;
32402 Bottom := Top + 20;
32403 end;
32404 Result.fMenu := 0;
32405 Result.fTextColor := clHighlight;
32406 Result.fCommandActions.aSetBkColor := PBM_SETBKCOLOR;
32407 end;
32408 {$ENDIF ASM_VERSION}
32409 //[END NewProgressbar]
32411 {$ENDIF USE_CONSTRUCTORS}
32413 {$IFDEF USE_CONSTRUCTORS}
32414 //[function NewProgressbarEx]
32415 function NewProgressbarEx( AParent: PControl; Options: TProgressbarOptions ): PControl;
32416 begin
32417 new( Result, CreateProgressbarEx( AParent, Options ) );
32418 end;
32419 //[END NewProgressbarEx]
32420 {$ELSE not_USE_CONSTRUCTORS}
32422 //[FUNCTION NewProgressbarEx]
32423 {$IFDEF ASM_VERSION}
32424 function NewProgressbarEx( AParent: PControl; Options: TProgressbarOptions ): PControl;
32426 PUSH EDX
32427 CALL NewProgressbar
32428 POP ECX
32429 XOR EDX, EDX
32430 SHR ECX, 1
32431 JNC @@notVert
32432 MOV DL, 4
32433 @@notVert:
32434 SHR ECX, 1
32435 JNC @@notSmooth
32436 INC EDX
32437 @@notSmooth:
32438 OR [EAX].TControl.fStyle, EDX
32439 end;
32440 {$ELSE ASM_VERSION} //Pascal
32441 function NewProgressbarEx( AParent: PControl; Options: TProgressbarOptions ): PControl;
32442 const ProgressBarFlags: array[ TProgressbarOption ] of Integer =
32443 (PBS_VERTICAL, PBS_SMOOTH );
32444 begin
32445 Result := NewProgressbar( AParent );
32446 Result.fStyle := Result.fStyle or DWORD( MakeFlags( @Options, ProgressBarFlags ) );
32447 end;
32448 {$ENDIF ASM_VERSION}
32449 //[END NewProgressbarEx]
32451 {$ENDIF USE_CONSTRUCTORS}
32453 //===================== List view ========================//
32455 //[FUNCTION WndProcNotify]
32456 {$IFDEF ASM_VERSION}
32457 function WndProcNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
32459 CMP word ptr [EDX].TMsg.message, WM_NOTIFY
32460 JNE @@ret_false
32461 PUSH ECX
32462 PUSH EDX
32463 PUSH offset[ID_SELF]
32464 MOV ECX, [EDX].TMsg.lParam
32465 PUSH [ECX].TNMHdr.hwndFrom
32466 CALL GetProp
32467 POP EDX
32468 TEST EAX, EAX
32469 JZ @@ret_false_ECX
32470 MOV ECX, [EAX].TControl.fHandle
32471 MOV [EDX].TMsg.hwnd, ECX
32472 POP ECX
32473 JMP TControl.EnumDynHandlers
32474 @@ret_false_ECX:
32475 POP ECX
32476 @@ret_false:
32477 XOR EAX, EAX
32478 end;
32479 {$ELSE ASM_VERSION} //Pascal
32480 function WndProcNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
32481 var NMhdr: PNMHdr;
32482 Child: PControl;
32483 begin
32484 Result := False;
32485 if Msg.message = WM_NOTIFY then
32486 begin
32487 NMhdr := Pointer( Msg.lParam );
32488 Child := Pointer( GetProp( NMhdr.hwndFrom, ID_SELF ) );
32489 if Child <> nil then
32490 begin
32491 {if Child = Self_ then
32492 begin
32493 Rslt := Self_.CallDefWndProc( Msg );
32494 Result := TRUE;
32496 else}
32497 begin
32498 Msg.hwnd := Child.fHandle;
32499 Result := EnumDynHandlers( Child, Msg, Rslt );
32500 end;
32501 end;
32502 end;
32503 end;
32504 {$ENDIF ASM_VERSION}
32505 //[END WndProcNotify]
32507 //[FUNCTION WndProcCommonNotify]
32508 {$IFDEF ASM_VERSION}
32509 function WndProcCommonNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
32511 CMP word ptr [EDX].TMsg.message, WM_NOTIFY
32512 JNE @@ret_false
32513 PUSH EBX
32514 MOV EBX, [EDX].TMsg.lParam
32515 MOV EDX, [EBX].TNMHdr.code
32517 @@chk_nm_click:
32518 XOR ECX, ECX
32519 CMP EDX, NM_CLICK
32520 JZ @@click
32521 CMP EDX, NM_RCLICK
32522 JNE @@chk_killfocus
32523 INC ECX
32524 @@click:
32525 MOV [EAX].TControl.fRightClick, CL
32527 MOV ECX, [EAX].TControl.fOnClick.TMethod.Code
32528 JECXZ @@fin_false
32529 MOV EDX, [EAX].TControl.fOnClick.TMethod.Data
32530 JMP @@fin_event
32532 @@fin_false:
32533 POP EBX
32534 @@ret_false:
32535 XOR EAX, EAX
32538 @@chk_killfocus:
32539 CMP EDX, NM_KILLFOCUS
32540 JNE @@chk_setfocus
32541 MOV ECX, [EAX].TControl.fOnLeave.TMethod.Code
32542 JECXZ @@fin_false
32543 MOV EDX, [EAX].TControl.fOnLeave.TMethod.Data
32544 JMP @@fin_event
32545 @@chk_setfocus:
32546 CMP EDX, NM_RETURN
32547 JE @@set_focus
32548 CMP EDX, NM_SETFOCUS
32549 JNE @@fin_false
32551 @@set_focus:
32552 MOV ECX, [EAX].TControl.fOnEnter.TMethod.Code
32553 JECXZ @@fin_false
32554 MOV EDX, [EAX].TControl.fOnEnter.TMethod.Data
32556 @@fin_event:
32557 XCHG EAX, EDX
32558 CALL ECX
32559 POP EBX
32560 MOV AL, 1
32561 end;
32562 {$ELSE ASM_VERSION} //Pascal
32563 function WndProcCommonNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
32564 var NMhdr: PNMHdr;
32565 begin
32566 Result := False;
32567 if Msg.message = WM_NOTIFY then
32568 begin
32569 NMHdr := Pointer( Msg.lParam );
32570 case NMHdr.code of
32571 NM_RCLICK,
32572 NM_CLICK: if assigned( Self_.fOnClick ) then
32573 begin
32574 Self_.fRightClick := NMHdr.code=NM_RCLICK;
32575 Self_.fOnClick( Self_ );
32576 Result := TRUE;
32577 end;
32578 NM_KILLFOCUS: if assigned( Self_.fOnLeave ) then
32579 Self_.fOnLeave( Self_ );
32580 NM_RETURN,
32581 NM_SETFOCUS: if assigned( Self_.fOnEnter ) then
32582 Self_.fOnEnter( Self_ );
32583 end;
32584 end;
32585 end;
32586 {$ENDIF ASM_VERSION}
32587 //[END WndProcCommonNotify]
32589 const ListViewStyles: array[ TListViewStyle ] of DWORD = ( LVS_ICON, LVS_SMALLICON,
32590 LVS_LIST, LVS_REPORT, LVS_REPORT or LVS_NOCOLUMNHEADER );
32591 ListViewFlags: array[ TListViewOption ] of Integer = ( LVS_ALIGNLEFT, LVS_AUTOARRANGE,
32592 $400 {LVS_BUTTON}, LVS_EDITLABELS, LVS_NOLABELWRAP,
32593 LVS_NOSCROLL, LVS_NOSORTHEADER,
32594 not LVS_SHOWSELALWAYS, not LVS_SINGLESEL, LVS_SORTASCENDING,
32595 LVS_SORTDESCENDING, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
32596 LVS_OWNERDATA, LVS_OWNERDRAWFIXED );
32598 ListViewExFlags: array[ TListViewOption ] of Integer = ( 0, 0,
32599 0, 0, 0, 0, 0, 0, 0, 0, 0, LVS_EX_GRIDLINES,
32600 LVS_EX_SUBITEMIMAGES, LVS_EX_CHECKBOXES, LVS_EX_TRACKSELECT,
32601 LVS_EX_HEADERDRAGDROP, LVS_EX_FULLROWSELECT, LVS_EX_ONECLICKACTIVATE,
32602 LVS_EX_TWOCLICKACTIVATE, LVS_EX_FLATSB, LVS_EX_REGIONAL,
32603 LVS_EX_INFOTIP, LVS_EX_UNDERLINEHOT, LVS_EX_MULTIWORKAREAS, 0, 0 );
32606 //[FUNCTION ApplyImageLists2Control]
32607 {$IFDEF ASM_VERSION}
32608 procedure ApplyImageLists2Control( Sender: PControl );
32610 PUSHAD
32611 XCHG ESI, EAX
32612 MOVZX ECX, [ESI].TControl.fCommandActions.aSetImgList
32613 JECXZ @@fin
32614 MOV EBP, ECX
32615 XOR EBX, EBX
32616 MOV BL, 32
32617 XOR EDI, EDI
32618 @@loo:
32619 MOV EAX, ESI
32620 MOV EDX, EBX
32621 CALL TControl.GetImgListIdx
32622 TEST EAX, EAX
32623 JZ @@nx
32624 CALL TImageList.GetHandle
32625 PUSH EAX
32626 PUSH EDI
32627 PUSH EBP
32628 PUSH ESI
32629 CALL TControl.Perform
32630 @@nx:
32631 INC EDI
32632 SHR EBX, 1
32633 JZ @@fin
32634 CMP BL, 16
32635 JGE @@loo
32636 XOR EBX, EBX
32637 JMP @@loo
32638 @@fin:
32639 POPAD
32640 end;
32641 {$ELSE ASM_VERSION} //Pascal
32642 procedure ApplyImageLists2Control( Sender: PControl );
32643 var IL: PImageList;
32644 begin
32645 if Sender.fCommandActions.aSetImgList = 0 then Exit;
32646 IL := Sender.ImageListNormal;
32647 if IL <> nil then
32648 Sender.Perform( Sender.fCommandActions.aSetImgList, LVSIL_NORMAL, IL.Handle );
32649 IL := Sender.ImageListSmall;
32650 if IL <> nil then
32651 Sender.Perform( Sender.fCommandActions.aSetImgList, LVSIL_SMALL, IL.Handle );
32652 IL := Sender.ImageListState;
32653 if IL <> nil then
32654 Sender.Perform( Sender.fCommandActions.aSetImgList, LVSIL_STATE, IL.Handle );
32655 end;
32656 {$ENDIF ASM_VERSION}
32657 //[END ApplyImageLists2Control]
32659 //[FUNCTION ApplyImageLists2ListView]
32660 {$IFDEF ASM_VERSION}
32661 procedure ApplyImageLists2ListView( Sender: PControl );
32663 PUSHAD
32665 XCHG ESI, EAX
32666 PUSH dword ptr [ESI].TControl.fLVOptions
32667 MOV EAX, ESP
32668 MOV EDX, offset[ListViewFlags]
32669 XOR ECX, ECX
32670 MOV CL, 25
32671 CALL MakeFlags
32672 POP ECX
32673 PUSH ECX
32675 MOV EDX, [ESI].TControl.fStyle
32676 //AND DH, 3
32677 AND DX, not $403F
32678 OR EDX, EAX
32680 MOVZX EAX, [ESI].TControl.fLVStyle
32681 OR EDX, [EAX*4 + offset ListViewStyles]
32683 MOV EAX, ESI
32684 CALL TControl.SetStyle
32686 MOV EAX, ESP
32687 MOV EDX, offset[ListViewExFlags]
32688 XOR ECX, ECX
32689 MOV CL, 23
32690 CALL MakeFlags
32691 POP EDX
32692 PUSH EAX
32693 PUSH $3FFF
32694 PUSH LVM_SETEXTENDEDLISTVIEWSTYLE
32695 PUSH ESI
32696 CALL TControl.Perform
32698 POPAD
32699 CALL ApplyImageLists2Control
32700 end;
32701 {$ELSE ASM_VERSION} //Pascal
32702 procedure ApplyImageLists2ListView( Sender: PControl );
32703 var Flags: DWORD;
32704 begin
32705 Flags := MakeFlags( @Sender.fLVOptions, ListViewFlags );
32706 Sender.Style := Sender.Style and not $403F
32707 or Flags or ListViewStyles[ Sender.fLVStyle ];
32708 Flags := MakeFlags( @Sender.fLVOptions, ListViewExFlags );
32709 Sender.Perform( LVM_SETEXTENDEDLISTVIEWSTYLE, $3FFF, Flags );
32710 ApplyImageLists2Control( Sender );
32711 end;
32712 {$ENDIF ASM_VERSION}
32713 //[END ApplyImageLists2ListView]
32715 {$IFDEF USE_CONSTRUCTORS}
32716 //[function NewListView]
32717 function NewListView( AParent: PControl; Style: TListViewStyle; Options: TListViewOptions;
32718 ImageListSmall, ImageListNormal, ImageListState: PImageList ): PControl;
32719 begin
32720 new( Result, CreateListView( AParent, Style, Options, ImageListSmall,
32721 ImageListNormal, ImageListState ) );
32722 end;
32723 //[END NewListView]
32724 {$ELSE not_USE_CONSTRUCTORS}
32726 //[FUNCTION NewListView]
32727 {$IFDEF ASM_VERSION}
32728 function NewListView( AParent: PControl; Style: TListViewStyle; Options: TListViewOptions;
32729 ImageListSmall, ImageListNormal, ImageListState: PImageList ): PControl;
32731 PUSH EDX
32732 PUSH ECX
32733 MOVZX EDX, DL
32734 MOV ECX, [EDX*4 + offset ListViewStyles]
32735 OR ECX, LVS_SHAREIMAGELISTS or WS_CHILD or WS_VISIBLE or WS_TABSTOP
32736 MOV EDX, offset[WC_LISTVIEW]
32737 PUSH 1
32738 PUSH offset[ListViewActions]
32739 CALL _NewCommonControl
32741 MOV EDX, ESP
32742 PUSH EAX
32743 XCHG EAX, EDX
32744 MOV EDX, offset ListViewFlags
32745 XOR ECX, ECX
32746 MOV CL, 25
32747 CALL MakeFlags
32748 XCHG EDX, EAX
32749 POP EAX
32750 MOV ECX, [EAX].TControl.fStyle
32751 AND ECX, not LVS_TYPESTYLEMASK
32752 OR EDX, ECX
32753 MOV [EAX].TControl.fStyle, EDX
32755 POP [EAX].TControl.fLVOptions
32756 POP EDX
32757 MOV [EAX].TControl.fLVStyle, DL
32758 MOV [EAX].TControl.fCreateWndExt, offset[ApplyImageLists2ListView]
32759 ADD [EAX].TControl.fBoundsRect.Right, 200-64
32760 ADD [EAX].TControl.fBoundsRect.Bottom, 150-64
32761 MOV ECX, [ImageListState]
32762 XOR EDX, EDX
32763 PUSHAD
32764 CALL TControl.SetImgListIdx
32765 POPAD
32766 MOV ECX, [ImageListSmall]
32767 MOV DL, 16
32768 PUSHAD
32769 CALL TControl.SetImgListIdx
32770 POPAD
32771 MOV ECX, [ImageListNormal]
32772 ADD EDX, EDX
32773 PUSH EAX
32774 CALL TControl.SetImgListIdx
32775 POP EAX
32776 MOV [EAX].TControl.fLVTextBkColor, clWindow
32777 XOR EDX, EDX
32778 //MOV [EAX].TControl.fMargin, EDX
32779 INC EDX
32780 MOV [EAX].TControl.fLookTabKeys, DL
32781 end;
32782 {$ELSE ASM_VERSION} //Pascal
32783 function NewListView( AParent: PControl; Style: TListViewStyle; Options: TListViewOptions;
32784 ImageListSmall, ImageListNormal, ImageListState: PImageList ): PControl;
32785 begin
32786 Result := _NewCommonControl( AParent, WC_LISTVIEW, ListViewStyles[ Style ] or
32787 LVS_SHAREIMAGELISTS or WS_CHILD or WS_VISIBLE or WS_TABSTOP or WS_CLIPCHILDREN,
32788 True, @ListViewActions );
32790 Result.fLVOptions := Options;
32791 Result.fLVStyle := Style;
32792 Result.fStyle := Result.fStyle and not LVS_TYPESTYLEMASK
32793 or DWORD( MakeFlags( @Options, ListViewFlags ) );
32794 Result.fCreateWndExt := ApplyImageLists2ListView;
32795 with Result.fBoundsRect do
32796 begin
32797 Right := Left + 200;
32798 Bottom := Top + 150;
32799 end;
32800 Result.ImageListSmall := ImageListSmall;
32801 Result.ImageListNormal := ImageListNormal;
32802 Result.ImageListState := ImageListState;
32803 Result.fLVTextBkColor := clWindow;
32804 Result.fLookTabKeys := [ tkTab ];
32805 //Result.fMargin := 0;
32806 end;
32807 {$ENDIF ASM_VERSION}
32808 //[END NewListView]
32810 {$ENDIF USE_CONSTRUCTORS}
32812 //===================== Tree view ========================//
32814 //[FUNCTION WndProcTreeView]
32815 {$IFDEF ASM_VERSION}
32816 function WndProcTreeView( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
32817 asm //cmd //opd
32818 CMP word ptr [EDX].TMsg.message, WM_NOTIFY
32819 JNZ @@ret_false
32820 PUSH EBX
32821 XCHG EBX, EAX
32822 MOV EDX, [EDX].TMsg.lParam
32823 LEA EAX, [EBX].TControl.fOnTVBeginDrag
32824 CMP word ptr [EDX].TNMTreeView.hdr.code, NM_RCLICK
32825 JNE @@chk_TVN_BEGINDRAG
32826 PUSH ECX
32827 PUSH ECX
32828 PUSH ESP
32829 CALL GetCursorPos
32830 MOV EAX, EBX
32831 MOV EDX, ESP
32832 MOV ECX, EDX
32833 CALL TControl.Screen2Client
32834 POP EAX
32835 AND EAX, $FFFF
32836 POP EDX
32837 SHL EDX, 16
32838 OR EAX, EDX
32839 PUSH EAX
32840 CALL GetShiftState
32841 PUSH EAX
32842 PUSH WM_RBUTTONUP
32843 PUSH [EBX].TControl.fHandle
32844 CALL PostMessage
32845 JMP @@2fin_false1
32847 @@chk_TVN_BEGINDRAG:
32848 {$IFDEF UNICODE_CTRLS}
32849 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_BEGINDRAGW
32850 JZ @@event_drag
32851 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_BEGINRDRAGW
32852 JZ @@event_drag
32853 {$ENDIF UNICODE_CTRLS}
32854 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_BEGINDRAG
32855 JZ @@event_drag
32856 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_BEGINRDRAG
32857 JNZ @@chk_BEGINLABELEDIT
32858 @@event_drag:
32859 MOV EDX, [EDX].TNMTreeView.itemNew.hItem
32860 @@event_call:
32861 MOV ECX, [EAX].TMethod.Code
32862 JECXZ @@2fin_false1
32863 MOV EAX, [EAX].TMethod.Data
32864 XCHG EBX, ECX
32865 XCHG EDX, ECX
32866 CALL EBX
32867 @@2fin_false1: JMP @@fin_false
32868 @@chk_BEGINLABELEDIT:
32869 LEA EAX, [EBX].TControl.fOnTVBeginEdit
32870 {$IFDEF UNICODE_CTRLS}
32871 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_BEGINLABELEDITW
32872 JZ @@beginlabeledit
32873 {$ENDIF UNICODE_CTRLS}
32874 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_BEGINLABELEDIT
32875 JNZ @@chk_ITEMEXPANDED //@@chk_DELETEITEM
32876 @@beginlabeledit:
32878 CMP [EBX].TControl.fDragging, 0
32879 JZ @@allow_LABELEDIT
32880 XOR EAX, EAX
32881 INC EAX
32882 MOV [ECX], EAX
32883 JMP @@ret_true
32885 @@allow_LABELEDIT:
32886 PUSH ECX // @Rslt
32888 MOV ECX, [EAX].TMethod.Code
32889 JECXZ @@2fin_false1
32890 PUSH EBX
32891 XCHG EBX, ECX
32892 MOV EDX, [EDX].TTVDispInfo.item.hItem
32893 XCHG EDX, ECX
32894 MOV EAX, [EAX].TMethod.Data
32895 CALL EBX
32896 TEST AL, AL
32897 SETZ AL // Rslt := not event result;
32898 POP EBX
32899 JZ @@ret_EAX
32900 INC [EBX].TControl.fEditing
32901 JMP @@ret_EAX
32903 @@call_EBX:
32904 CALL EBX
32905 @@2fin_false:
32906 JMP @@fin_false
32907 @@chk_ITEMEXPANDED:
32908 LEA EAX, [EBX].TControl.fOnTVExpanded
32909 {$IFDEF UNICODE_CTRLS}
32910 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_ITEMEXPANDEDW
32911 JZ @@itemexpanded
32912 {$ENDIF UNICODE_CTRLS}
32913 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_ITEMEXPANDED
32914 JNZ @@chk_SELCHANGING
32915 @@itemexpanded:
32916 MOV ECX, [EAX].TMethod.Code
32917 JECXZ @@2fin_false
32918 CMP [EDX].TNMTreeView.action, TVE_EXPAND
32919 PUSH ECX
32920 SETZ CL
32921 XCHG ECX, [ESP]
32922 JMP @@event_drag
32923 @@chk_SELCHANGING:
32924 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_SELCHANGING
32925 JNE @@chk_ITEMEXPANDING
32926 XCHG EAX, ECX
32927 MOV ECX, [EBX].TControl.fOnTVSelChanging.TMethod.Code
32928 @@2fin_false2:
32929 JECXZ @@2fin_false
32930 PUSH EAX //@Rslt
32931 PUSH [EDX].TNMTreeView.itemNew.hItem
32932 XCHG ECX, EBX //EBX=OnTVSelChanging.Code ECX=Sender
32933 XCHG ECX, EDX //EDX=Sender ECX=Msg
32934 MOV ECX, [ECX].TNMTreeView.itemOld.hItem
32935 MOV EAX, [EDX].TControl.fOnTVSelChanging.TMethod.Data
32936 JMP @@111
32938 @@chk_ITEMEXPANDING:
32939 {$IFDEF UNICODE_CTRLS}
32940 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_ITEMEXPANDINGW
32941 JZ @@itemexpanding
32942 {$ENDIF UNICODE_CTRLS}
32943 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_ITEMEXPANDING
32944 JNE @@chk_ENDLABELEDIT
32945 @@itemexpanding:
32946 XCHG EAX, ECX
32947 MOV ECX, [EBX].TControl.fOnTVExpanding.TMethod.Code
32948 JECXZ @@2fin_false2
32949 PUSH EAX // @Rslt
32950 CMP [EDX].TNMTreeView.action, TVE_EXPAND
32951 PUSH ECX
32952 SETZ CL
32953 XCHG ECX, [ESP]
32954 XCHG ECX, EBX //EBX=OnTVExpanding.Code ECX=Seneder
32955 XCHG EDX, ECX //ECX=Msg EDX=Sender
32956 MOV ECX, [ECX].TNMTreeView.itemNew.hItem //ECX=Item
32957 MOV EAX, [EDX].TControl.fOnTVExpanding.TMethod.Data //EAX=object
32958 @@111:
32959 CALL EBX
32960 TEST EAX, EAX
32961 SETZ AL // Rslt := not event result;
32962 @@ret_EAX:
32963 POP EDX //EDX=@Rslt
32964 MOVZX EAX, AL
32965 NEG EAX
32966 MOV [EDX], EAX
32967 @@ret_true:
32968 MOV AL, 1
32969 POP EBX
32971 @@chk_ENDLABELEDIT:
32972 {$IFDEF UNICODE_CTRLS}
32973 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_ENDLABELEDITW
32974 JZ @@endlabeledit
32975 {$ENDIF UNICODE_CTRLS}
32976 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_ENDLABELEDIT
32977 JNZ @@chk_SELCHANGED
32978 @@endlabeledit:
32979 MOV [EBX].TControl.fEditing, 0
32980 XCHG EAX, ECX
32981 MOV ECX, [EBX].TControl.fOnTVEndEdit.TMethod.Code
32982 JECXZ @@ret_1
32983 PUSH EAX
32984 PUSH EBX
32985 PUSH 0
32987 XCHG EDX, EBX
32988 MOV EAX, [EBX].TTVDispInfo.item.pszText
32989 PUSH EDX
32990 PUSH ECX
32991 XCHG EAX, EDX
32992 {$IFDEF UNICODE_CTRLS}
32993 CMP [EBX].TNMTreeView.hdr.code, TVN_ENDLABELEDITW
32994 JNZ @@endlabeleditA
32995 CALL TControl.TVGetItemTextW
32996 JMP @@NewTxt_ready
32997 @@endlabeleditA:
32998 {$ENDIF UNICODE_CTRLS}
32999 TEST EDX, EDX
33000 JNZ @@prepare_NewTxt
33001 // NewTxt := [EDX].TControl.TVItemText[ hItem ]
33002 LEA ECX, [ESP + 8]
33003 MOV EDX, [EBX].TTVDispInfo.item.hItem
33004 CALL TControl.TVGetItemText
33005 JMP @@NewTxt_ready
33006 @@prepare_NewTxt:
33007 LEA EAX, [ESP+8]
33008 CALL System.@LStrFromPChar
33009 @@NewTxt_ready:
33010 POP ECX
33011 POP EDX
33012 POP EAX
33013 PUSH EAX
33014 PUSH EAX
33015 MOV EAX, [EDX].TControl.fOnTVEndEdit.TMethod.Data
33016 MOV EBX, [EBX].TTVDispInfo.item.hItem
33017 XCHG ECX, EBX
33018 CALL EBX
33019 XCHG EBX, EAX
33020 CALL RemoveStr
33021 XCHG EAX, EBX
33022 POP EBX
33023 JMP @@ret_EAX
33024 @@ret_1:
33025 INC ECX
33026 MOV [EAX], ECX
33027 JMP @@ret_true
33029 @@chk_SELCHANGED:
33030 {$IFDEF UNICODE_CTRLS}
33031 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_SELCHANGEDW
33032 JZ @@selchanged
33033 {$ENDIF UNICODE_CTRLS}
33034 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_SELCHANGED
33035 JNZ @@fin_false
33036 @@selchanged:
33037 XCHG EAX, EBX
33038 CALL TControl.DoSelChange
33040 @@fin_false:
33041 POP EBX
33042 @@ret_false:
33043 XOR EAX, EAX
33044 end;
33045 {$ELSE ASM_VERSION} //Pascal
33046 function WndProcTreeView( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
33047 var NM: PNMTreeView;
33048 DI: PTVDispInfo;
33049 P: TPoint;
33050 S: String;
33051 begin
33052 if Msg.message = WM_NOTIFY then
33053 begin
33054 NM := Pointer( Msg.lParam );
33055 case NM.hdr.code of
33056 NM_RCLICK:
33057 begin
33058 GetCursorPos( P );
33059 P := Self_.Screen2Client( P );
33060 PostMessage( Self_.fHandle, WM_RBUTTONUP, MK_RBUTTON or GetShiftState,
33061 (P.x and $FFFF) or (P.y shl 16) );
33062 end;
33064 {$IFDEF UNICODE_CTRLS}
33065 TVN_BEGINDRAGW, TVN_BEGINRDRAGW,
33066 {$ENDIF} TVN_BEGINDRAG, TVN_BEGINRDRAG:
33067 if Assigned( Self_.fOnTVBeginDrag ) then
33068 Self_.fOnTVBeginDrag( Self_, NM.itemNew.hItem );
33069 TVN_BEGINLABELEDIT {$IFDEF UNICODE_CTRLS}, TVN_BEGINLABELEDITW{$ENDIF}:
33070 begin
33071 if Self_.fDragging then
33072 begin
33073 Rslt := 1; // do not allow edit while dragging
33074 Result := TRUE;
33075 Exit;
33076 end;
33077 DI := Pointer( NM );
33078 if Assigned( Self_.fOnTVBeginEdit ) then
33079 begin
33080 Rslt := Integer( not Self_.fOnTVBeginEdit( Self_, DI.item.hItem ) );
33081 if Rslt = 0 then
33082 Self_.fEditing := TRUE;
33083 Result := TRUE;
33084 Exit;
33085 end;
33086 end;
33087 TVN_ENDLABELEDIT {$IFDEF UNICODE_CTRLS}, TVN_ENDLABELEDITW {$ENDIF}:
33088 begin
33089 DI := Pointer( NM );
33090 if Assigned( Self_.fOnTVEndEdit ) then
33091 begin
33092 S := DI.item.pszText;
33093 if DI.item.pszText = nil then
33094 begin
33095 {$IFDEF UNICODE_CTRLS}
33096 if NM.hdr.code = TVN_ENDLABELEDITW then
33097 S := Self_.TVItemTextW[ DI.item.hItem ]
33098 else
33099 {$ENDIF UNICODE_CTRLS}
33100 S := Self_.TVItemText[ DI.item.hItem ];
33101 end;
33102 if Self_.fOnTVEndEdit( Self_, DI.item.hItem, S )
33103 then Rslt := 1
33104 else Rslt := 0;
33106 else
33107 Rslt := 1;
33108 Self_.fEditing := FALSE;
33109 Result := True;
33110 Exit;
33111 end;
33112 TVN_ITEMEXPANDING {$IFDEF UNICODE_CTRLS}, TVN_ITEMEXPANDINGW {$ENDIF}:
33113 begin
33114 if Assigned( Self_.fOnTVExpanding ) then
33115 begin
33116 Rslt := Integer( not Self_.fOnTVExpanding( Self_, NM.itemNew.hItem,
33117 NM.action = TVE_EXPAND ) );
33118 Result := TRUE;
33119 Exit;
33120 end;
33121 end;
33122 TVN_ITEMEXPANDED {$IFDEF UNICODE_CTRLS}, TVN_ITEMEXPANDEDW {$ENDIF}:
33123 if Assigned( Self_.fOnTVExpanded ) then
33124 Self_.fOnTVExpanded( Self_, NM.itemNew.hItem, NM.action=TVE_EXPAND );
33125 {TVN_DELETEITEM:
33126 if Assigned( Self_.fOnTVDelete ) then
33127 Self_.fOnTVDelete( Self_, NM.itemOld.hItem );}
33128 //------------------ by Sergey Shisminzev:
33129 TVN_SELCHANGING {$IFDEF UNICODE_CTRLS}, TVN_SELCHANGINGW {$ENDIF}:
33130 begin
33131 if Assigned( Self_.fOnTVSelChanging ) then
33132 begin
33133 Rslt := Integer( not Self_.fOnTVSelChanging( Self_, NM.itemOld.hItem, NM.itemNew.hItem ) );
33134 Result := TRUE;
33135 Exit;
33136 end;
33137 end;
33138 //----------------------------------------
33139 TVN_SELCHANGED {$IFDEF UNICODE_CTRLS}, TVN_SELCHANGEDW {$ENDIF}:
33140 Self_.DoSelChange;
33141 end;
33142 end;
33143 Result := False;
33144 end;
33145 {$ENDIF ASM_VERSION}
33146 //[END WndProcTreeView]
33148 //[function ProcTVDeleteItem]
33149 function ProcTVDeleteItem( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
33150 var NM: PNMTreeView;
33151 begin
33152 if Msg.message = WM_NOTIFY then
33153 begin
33154 NM := Pointer( Msg.lParam );
33155 case NM.hdr.code of
33156 TVN_DELETEITEM:
33157 if Assigned( Self_.fOnTVDelete ) then
33158 Self_.fOnTVDelete( Self_, NM.itemOld.hItem );
33159 end;
33160 end;
33161 Result := FALSE;
33162 end;
33164 //[procedure ClearTreeView]
33165 procedure ClearTreeView( TV: PControl );
33166 begin
33167 TV.TVDelete( TVI_ROOT );
33168 end;
33170 const
33171 TreeViewFlags: array[ TTreeViewOption ] of Integer = ( not TVS_HASLINES, TVS_LINESATROOT,
33172 not TVS_HASBUTTONS, TVS_EDITLABELS, not TVS_SHOWSELALWAYS,
33173 not TVS_DISABLEDRAGDROP, TVS_NOTOOLTIPS, TVS_CHECKBOXES,
33174 TVS_TRACKSELECT, TVS_SINGLEEXPAND, TVS_INFOTIP,
33175 TVS_FULLROWSELECT, TVS_NOSCROLL, TVS_NONEVENHEIGHT );
33177 {$IFDEF USE_CONSTRUCTORS}
33178 //[function NewTreeView]
33179 function NewTreeView( AParent: PControl; Options: TTreeViewOptions;
33180 ImgListNormal, ImgListState: PImageList ): PControl;
33181 begin
33182 new( Result, CreateTreeView( AParent, Options, ImgListNormal, ImgListState ) );
33183 end;
33184 {$ELSE not_USE_CONSTRUCTORS}
33186 //[FUNCTION NewTreeView]
33187 {$IFDEF ASM_VERSION}
33188 function NewTreeView( AParent: PControl; Options: TTreeViewOptions;
33189 ImgListNormal, ImgListState: PImageList ): PControl;
33190 asm //cmd //opd
33191 PUSH EBX
33192 PUSH ECX
33193 PUSH EAX
33194 PUSH EDX
33195 MOV EAX, ESP
33196 MOV EDX, offset[TreeViewFlags]
33197 XOR ECX, ECX
33198 MOV CL, 13
33199 CALL MakeFlags
33200 POP EDX
33201 OR EAX, WS_VISIBLE or WS_CHILD or WS_TABSTOP
33202 XCHG ECX, EAX
33203 POP EAX
33204 MOV EDX, offset[WC_TREEVIEW]
33205 PUSH 1
33206 PUSH offset[TreeViewActions]
33207 CALL _NewCommonControl
33208 MOV EBX, EAX
33209 MOV [EBX].TControl.fCreateWndExt, offset[ApplyImageLists2Control]
33210 MOV [EBX].TControl.fColor, clWindow
33211 MOV EDX, offset[WndProcTreeView]
33212 CALL TControl.AttachProc
33213 ADD [EBX].TControl.fBoundsRect.Right, 150-64
33214 ADD [EBX].TControl.fBoundsRect.Bottom, 200-64
33215 MOV EAX, EBX
33216 XOR EDX, EDX
33217 MOV DL, 32
33218 POP ECX // ImageListNormal
33219 CALL TControl.SetImgListIdx
33220 MOV EAX, EBX
33221 XOR EDX, EDX
33222 MOV ECX, [ImgListState]
33223 CALL TControl.SetImgListIdx
33224 MOV byte ptr [EBX].TControl.fLookTabKeys, 1
33225 XCHG EAX, EBX
33226 POP EBX
33227 end;
33228 {$ELSE ASM_VERSION} //Pascal
33229 function NewTreeView( AParent: PControl; Options: TTreeViewOptions;
33230 ImgListNormal, ImgListState: PImageList ): PControl;
33231 var Flags: Integer;
33232 begin
33233 Flags := MakeFlags( @Options, TreeViewFlags );
33234 Result := _NewCommonControl( AParent, WC_TREEVIEW, Flags or WS_VISIBLE or
33235 WS_CHILD or WS_TABSTOP, True, @TreeViewActions );
33236 Result.fCreateWndExt := ApplyImageLists2Control;
33237 Result.fColor := clWindow;
33238 Result.AttachProc( WndProcTreeView );
33239 with Result.fBoundsRect do
33240 begin
33241 Right := Left + 150;
33242 Bottom := Top + 200;
33243 end;
33244 Result.ImageListNormal := ImgListNormal;
33245 Result.ImageListState := ImgListState;
33246 //Result.fLVTextBkColor := clWindow;
33247 Result.fLookTabKeys := [ tkTab ];
33248 end;
33249 {$ENDIF ASM_VERSION}
33250 //[END NewTreeView]
33252 {$ENDIF USE_CONSTRUCTORS}
33254 //===================== Tab Control ========================//
33256 //[FUNCTION WndProcTabControl]
33257 {$IFDEF ASM_VERSION}
33258 function WndProcTabControl( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
33259 asm //cmd //opd
33260 PUSH EBP
33261 PUSH EBX
33262 PUSH ESI
33263 PUSH EDI
33264 MOV EBX, EAX
33265 CMP word ptr [EDX].TMsg.message, WM_NOTIFY
33266 JNZ @@chk_WM_SIZE
33267 MOV EDX, [EDX].TMsg.lParam
33268 CMP word ptr [EDX].TNMHdr.code, TCN_SELCHANGE
33269 JNZ @@ret_false
33271 CALL TControl.GetCurIndex
33272 XCHG EDI, EAX
33273 CMP EDI, [EBX].TControl.fCurIndex
33274 PUSHFD // WasActive = ZF
33276 MOV [EBX].TControl.FCurIndex, EDI
33278 MOV EAX, EBX
33279 CALL TControl.GetItemsCount
33280 XCHG ESI, EAX // ESI := Self_.Count
33282 @@loo: DEC ESI
33283 JS @@e_loo
33284 MOV EDX, ESI
33285 MOV EAX, EBX
33286 CALL TControl.GetPages
33288 CMP ESI, EDI
33289 PUSH EAX
33290 SETZ DL
33291 CALL TControl.SetVisible
33292 POP EAX
33293 CMP ESI, EDI
33294 JNE @@nx_loo
33295 CALL TControl.BringToFront
33296 @@nx_loo:
33297 JMP @@loo
33298 @@e_loo:
33299 MOV EAX, EBX
33300 CALL TControl.ParentForm
33301 TEST EAX, EAX
33302 JZ @@1
33303 MOV ECX, [EAX].TControl.fCurrentControl
33304 JECXZ @@1
33305 MOV EAX, EBX
33306 MOV DL, 1
33307 CALL TControl.SetFocused
33308 MOV EAX, EBX
33309 CALL TControl.Invalidate
33310 TEST byte ptr [EBX].TControl.fStyle+1, $10
33311 JNZ @@1
33312 MOV EAX, EBX
33313 XOR EDX, EDX
33314 MOV DL, VK_TAB
33315 CALL TControl.GotoControl
33316 @@1:
33317 POPFD
33318 JZ @@ret_false
33320 MOV ECX, [EBX].TControl.fOnSelChange.TMethod.Code
33321 JECXZ @@ret_false
33322 MOV EDX, EBX
33323 MOV EAX, [EBX].TControl.fOnSelChange.TMethod.Data
33324 CALL ECX
33325 JMP @@ret_false
33326 @@chk_WM_SIZE:
33327 CMP word ptr [EDX].TMsg.message, WM_SIZE
33328 JNE @@ret_false
33329 ADD ESP, -16
33330 PUSH ESP
33331 PUSH [EBX].TControl.fHandle
33332 CALL Windows.GetClientRect
33333 PUSH ESP
33334 PUSH 0
33335 PUSH TCM_ADJUSTRECT
33336 PUSH EBX
33337 CALL TControl.Perform
33338 MOV EAX, EBX
33339 CALL TControl.GetItemsCount
33340 XCHG ESI, EAX
33341 @@loo2:
33342 DEC ESI
33343 JS @@e_loo2
33344 MOV EDX, ESI
33345 MOV EAX, EBX
33346 CALL TControl.GetPages
33347 MOV EDX, ESP
33348 CALL TControl.SetBoundsRect
33349 JMP @@loo2
33350 @@e_loo2:
33351 ADD ESP, 16
33352 @@ret_false:
33353 XOR EAX, EAX
33354 POP EDI
33355 POP ESI
33356 POP EBX
33357 POP EBP
33358 end;
33359 {$ELSE ASM_VERSION} //Pascal
33360 function WndProcTabControl( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
33361 var Hdr: PNMHdr;
33362 Page: PControl;
33363 I, A: Integer;
33364 R: TRect;
33365 Form: PControl;
33366 WasActive: Boolean;
33367 begin
33368 case Msg.message of
33369 WM_NOTIFY:
33370 begin
33371 Hdr := Pointer( Msg.lParam );
33372 case Hdr.code of
33373 TCN_SELCHANGE:
33374 begin
33375 A := Self_.Perform( TCM_GETCURSEL, 0, 0 );
33376 WasActive := Self_.fCurIndex = A;
33377 Self_.fCurIndex := A;
33378 for I := 0 to Self_.Count - 1 do
33379 begin
33380 Page := Self_.Pages[ I ];
33381 Page.Visible := A = I;
33382 if A = I then
33383 Page.BringToFront;
33384 end;
33385 Form := Self_.ParentForm;
33386 if Form <> nil then
33387 begin
33388 if Form.fCurrentControl <> nil then
33389 begin
33390 Self_.Focused := True;
33391 Self_.Invalidate;
33392 if not Longbool( Self_.fStyle and TCS_FOCUSONBUTTONDOWN ) then
33393 Self_.GotoControl( VK_TAB );
33394 end;
33395 end;
33396 if not WasActive then
33397 if Assigned( Self_.fOnSelChange ) then
33398 Self_.fOnSelChange( Self_ );
33399 //Result := True;
33400 end;
33401 end;
33402 end;
33403 WM_SIZE:
33404 begin
33405 GetClientRect( Self_.fHandle, R );
33406 Self_.Perform( TCM_ADJUSTRECT, 0, Integer( @R ) );
33407 for I := 0 to Self_.Count - 1 do
33408 begin
33409 Page := Self_.Pages[ I ];
33410 Page.BoundsRect := R;
33411 end;
33412 end;
33413 end;
33414 Result := False;
33415 end;
33416 {$ENDIF ASM_VERSION}
33417 //[END WndProcTabControl]
33419 const TabControlFlags: array[ TTabControlOption ] of Integer = ( TCS_BUTTONS,
33420 TCS_FIXEDWIDTH, not TCS_FOCUSNEVER,
33421 TCS_FIXEDWIDTH or TCS_FORCEICONLEFT, TCS_FIXEDWIDTH or TCS_FORCELABELLEFT,
33422 TCS_MULTILINE, TCS_MULTISELECT, TCS_RIGHTJUSTIFY, TCS_SCROLLOPPOSITE,
33423 TCS_BOTTOM, TCS_VERTICAL, TCS_FLATBUTTONS, TCS_HOTTRACK, 0, TCS_OWNERDRAWFIXED );
33425 {$IFDEF USE_CONSTRUCTORS}
33426 //[function NewTabControl]
33427 function NewTabControl( AParent: PControl; Tabs: array of String; Options: TTabControlOptions;
33428 ImgList: PImageList; ImgList1stIdx: Integer ): PControl;
33429 begin
33430 new( Result, CreateTabControl( AParent, Tabs, Options, ImgList, ImgList1stIdx ) );
33431 end;
33432 //[END NewTabControl]
33433 {$ELSE not_USE_CONSTRUCTORS}
33435 //[FUNCTION NewTabControl]
33436 {$IFDEF ASM_VERSION}
33437 function NewTabControl( AParent: PControl; Tabs: array of String; Options: TTabControlOptions;
33438 ImgList: PImageList; ImgList1stIdx: Integer ): PControl;
33439 asm //cmd //opd
33440 PUSH EBX
33441 PUSH ESI
33442 PUSH EDI
33443 XCHG EBX, EAX
33444 PUSH EDX
33445 PUSH ECX
33446 LEA EAX, [Options]
33447 MOV EDX, offset[TabControlFlags]
33448 XOR ECX, ECX
33449 MOV CL, 13
33450 CALL MakeFlags
33451 TEST byte ptr [Options], 4
33452 JZ @@0
33453 OR EAX, WS_TABSTOP or TCS_FOCUSONBUTTONDOWN
33454 @@0: OR EAX, WS_CHILD or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or WS_VISIBLE
33455 XCHG ECX, EAX
33456 XCHG EAX, EBX
33457 MOV EDX, offset[WC_TABCONTROL]
33458 PUSH 1
33459 PUSH offset[TabControlActions]
33460 CALL _NewCommonControl
33461 MOV EBX, EAX
33462 TEST [Options], 2 shl (tcoBorder - 1)
33463 JNZ @@borderfixed
33464 AND [EBX].TControl.fExStyle, not WS_EX_CLIENTEDGE
33465 @@borderfixed:
33466 MOV EDX, offset[WndProcTabControl]
33467 CALL TControl.AttachProc
33468 ADD [EBX].TControl.fBoundsRect.Right, 100-64
33469 ADD [EBX].TControl.fBoundsRect.Bottom, 100-64
33470 MOV ECX, [ImgList]
33471 JECXZ @@2
33472 XCHG EAX, ECX
33473 CALL TImageList.GetHandle
33474 PUSH EAX
33475 PUSH 0
33476 PUSH TCM_SETIMAGELIST
33477 PUSH EBX
33478 CALL TControl.Perform
33479 @@2:
33480 POP EDI // EDI = High(Tabs)
33481 POP ESI // ESI = Tabs
33482 XOR EDX, EDX // EBP := 0 (=I)
33483 MOV EAX, [ImgList1stIdx] //(=II)
33484 @@loop:
33485 CMP EDX, EDI
33486 JG @@e_loop
33487 PUSH EAX
33488 PUSH EDX
33489 PUSH EAX
33490 LODSD
33491 XCHG ECX, EAX
33492 MOV EAX, EBX
33493 CALL TControl.TC_Insert
33494 POP EDX
33495 POP EAX
33496 INC EAX
33497 INC EDX
33498 JMP @@loop
33499 @@e_loop:
33500 MOV byte ptr [EBX].TControl.fLookTabKeys, 1
33501 XCHG EAX, EBX
33502 POP EDI
33503 POP ESI
33504 POP EBX
33505 end;
33506 {$ELSE ASM_VERSION} //Pascal
33507 function NewTabControl( AParent: PControl; Tabs: array of String; Options: TTabControlOptions;
33508 ImgList: PImageList; ImgList1stIdx: Integer ): PControl;
33509 var I, II : Integer;
33510 Flags: Integer;
33511 begin
33512 Flags := MakeFlags( @Options, TabControlFlags );
33513 if tcoFocusTabs in Options then
33514 Flags := Flags or (WS_TABSTOP or TCS_FOCUSONBUTTONDOWN);
33515 Result := _NewCommonControl( AParent, WC_TABCONTROL,
33516 Flags or (WS_CHILD or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or WS_VISIBLE), True,
33517 @TabControlActions );
33518 //***
33519 if not( tcoBorder in Options ) then
33520 begin
33521 Result.fExStyle := Result.fExStyle and not WS_EX_CLIENTEDGE;
33522 end;
33523 Result.AttachProc( WndProcTabControl );
33524 with Result.fBoundsRect do
33525 begin
33526 Right := Left + 100;
33527 Bottom := Top + 100;
33528 end;
33529 if ImgList <> nil then
33530 Result.Perform( TCM_SETIMAGELIST, 0, ImgList.Handle );
33531 II := ImgList1stIdx;
33532 for I := 0 to High( Tabs ) do
33533 begin
33534 Result.TC_Insert( I, Tabs[ I ], II );
33535 Inc( II );
33536 end;
33537 Result.fLookTabKeys := [ tkTab ];
33538 end;
33539 {$ENDIF ASM_VERSION}
33540 //[END NewTabControl]
33542 {$ENDIF USE_CONSTRUCTORS}
33544 //===================== Tool bar ========================//
33546 //[FUNCTION WndProcToolbarCtr]
33547 {$IFDEF ASM_noVERSION} //TTN_NEEDTEXTW
33548 function WndProcToolbarCtrl(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
33550 CMP word ptr [EDX].TMsg.message, WM_WINDOWPOSCHANGED
33551 JNE @@chk_CM_COMMAND
33552 MOV dword ptr [ECX], 0 // Rslt := 0
33553 MOV ECX, [EAX].TControl.fOnResize.TMethod.Code
33554 JECXZ @@ret_true
33555 XCHG EDX, EAX // Sender := Self_
33556 MOV EAX, [EDX].TControl.fOnResize.TMethod.Data
33557 CALL ECX // Self_.fOnResize
33558 @@ret_true:
33559 MOV AL, 1 // Result := TRUE
33561 @@chk_CM_COMMAND:
33562 CMP word ptr [EDX].TMsg.message, CM_COMMAND
33563 JNE @@chk_WM_NOTIFY
33564 MOVZX ECX, word ptr [EDX].TMsg.wParam
33565 MOV [EAX].TControl.fCurItem, ECX
33566 PUSH EAX
33567 PUSH 0
33568 PUSH ECX
33569 PUSH TB_COMMANDTOINDEX
33570 PUSH EAX
33571 CALL TControl.Perform
33572 PUSH EAX
33574 PUSH VK_RETURN
33575 CALL GetKeyState
33576 TEST EAX, EAX
33577 SETL DL
33578 POP ECX
33579 POP EAX
33580 MOV [EAX].TControl.fCurIndex, ECX
33581 MOV [EAX].TControl.fRightClick, DL
33582 @@ret_false:
33583 XOR EAX, EAX
33586 @@chk_WM_NOTIFY:
33587 CMP word ptr [EDX].TMsg.message, WM_NOTIFY
33588 JNE @@ret_false
33589 MOV EDX, [EDX].TMsg.lParam
33590 MOV ECX, [EDX].TTooltipText.hdr.code
33591 CMP ECX, TTN_NEEDTEXT
33592 JNE @@chk_NM_RCLICK
33593 PUSH EAX
33594 PUSH EDX
33595 MOV EDX, [EDX].TTooltipText.hdr.idFrom
33596 MOV ECX, [EAX].TControl.fTBttCmd
33597 OR EAX, -1
33598 JECXZ @@idxReady
33599 XCHG EAX, ECX
33600 CALL TList.IndexOf
33601 @@idxReady: // EAX = -1 or index of button tooltip
33602 TEST EAX, EAX
33603 POP EDX
33604 LEA EDX, [EDX].TTooltipText.szText
33605 MOV byte ptr [EDX], 0
33606 POP ECX
33607 JL @@ret_true
33608 MOV ECX, [ECX].TControl.fTBttTxt
33609 MOV ECX, [ECX].TStrList.fList
33610 MOV ECX, [ECX].TList.fItems
33611 MOV EAX, [ECX+EAX*4]
33612 XCHG EAX, EDX
33613 XOR ECX, ECX
33614 MOV CL, 79
33615 CALL StrLCopy
33616 JMP @@ret_true
33617 @@chk_NM_RCLICK:
33618 CMP ECX, NM_RCLICK
33619 JNE @@chk_NM_CLICK
33620 OR [EAX].TControl.fRightClick, 1
33621 MOV ECX, [EDX].TNMMouse.dwItemSpec
33622 MOV [EAX].TControl.fCurItem, -1
33623 PUSH EAX
33624 PUSH 0
33625 PUSH ECX
33626 PUSH TB_COMMANDTOINDEX
33627 PUSH EAX
33628 CALL TControl.Perform
33629 POP EDX
33630 MOV [EDX].TControl.fCurIndex, EAX
33631 XOR EAX, EAX
33633 @@chk_NM_CLICK:
33634 CMP ECX, NM_CLICK
33635 JNE @@chk_TBN_DROPDOWN
33636 MOV [EAX].TControl.fRightClick, 0
33637 OR [EAX].TControl.fCurItem, -1
33638 OR [EAX].TControl.fCurIndex, -1
33639 CMP [EDX].TTBNotify.iItem, -1
33640 SETNZ AL
33642 @@chk_TBN_DROPDOWN:
33643 CMP ECX, TBN_DROPDOWN
33644 JNE @@ret_false
33645 MOV EDX, [EDX].TTBNotify.iItem
33646 MOV [EAX].TControl.fCurItem, EDX
33647 PUSH EAX
33648 CALL TControl.TBItem2Index
33649 POP EDX
33650 MOV [EDX].TControl.fCurIndex, EAX
33651 MOV ECX, [EDX].TControl.fOnDropDown.TMethod.Code
33652 JECXZ @@ret_z
33653 MOV EAX, [EDX].TControl.fOnDropDown.TMethod.Data
33654 CALL ECX
33655 @@ret_z:
33656 XOR EAX, EAX
33657 end;
33658 {$ELSE ASM_VERSION} //Pascal
33659 function WndProcToolbarCtrl(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
33660 var lpttt: PTooltipText;
33661 idBtn, Idx: Integer;
33662 var Notify: PTBNotify;
33663 Mouse: PNMMouse;
33664 {$IFNDEF _FPC}
33665 {$IFNDEF _D2}
33666 var Wstr: WideString;
33667 {$ENDIF _D2}
33668 {$ENDIF _FPC}
33669 begin
33670 Result := False;
33671 if Msg.message = WM_WINDOWPOSCHANGED then
33672 begin
33673 if Assigned( Self_.fOnResize ) then
33674 Self_.fOnResize( Self_ );
33675 Result := TRUE;
33676 Rslt := 0;
33678 else if Msg.message = CM_COMMAND then
33679 begin
33680 Self_.fCurItem := Loword( Msg.wParam );
33681 Self_.fCurIndex := Self_.Perform( TB_COMMANDTOINDEX, Loword( Msg.wParam ), 0 );
33682 Self_.fRightClick := GetKeyState( VK_RBUTTON ) < 0;
33684 else if Msg.message = WM_NOTIFY then
33685 begin
33686 lpttt := Pointer( Msg.lParam );
33687 Notify := Pointer( Msg.lParam );
33688 case lpttt.hdr.code of
33689 TTN_NEEDTEXT:
33690 begin
33691 Result := True;
33692 idBtn := lpttt.hdr.idFrom;
33693 Idx := -1;
33694 if Self_.fTBttCmd <> nil then
33695 Idx := Self_.fTBttCmd.IndexOf( Pointer( idBtn ) );
33696 lpttt.szText[ 0 ] := #0;
33697 if Idx >= 0 then
33698 StrLCopy( lpttt.szText, Self_.fTBttTxt.fList.fItems[ Idx ], 79 );
33699 Exit;
33700 end;
33701 // for Windows XP
33702 {$IFNDEF _FPC}
33703 {$IFNDEF _D2}
33704 TTN_NEEDTEXTW:
33705 begin
33706 Result := True;
33707 idBtn := lpttt.hdr.idFrom;
33708 Idx := -1;
33709 if Self_.fTBttCmd <> nil then
33710 Idx := Self_.fTBttCmd.IndexOf( Pointer( idBtn ) );
33711 FillChar( lpttt.szText[ 0 ], 160, 0 );
33712 if Idx >= 0 then
33713 begin
33714 WStr := Self_.fTBttTxt.Items[ Idx ];
33715 if WStr <> '' then
33716 Move( Wstr[ 1 ], lpttt.szText, Min( 158, (Length( WStr ) + 1) * 2 ) );
33717 end;
33718 Exit;
33719 end;
33720 {$ENDIF _D2}
33721 {$ENDIF _FPC}
33722 NM_RCLICK:
33723 begin
33724 Mouse := Pointer( Msg.lParam );
33725 Self_.fCurItem := Mouse.dwItemSpec;
33726 Self_.fCurIndex := Self_.Perform( TB_COMMANDTOINDEX, Mouse.dwItemSpec, 0 );
33727 Self_.fRightClick := GetKeyState( VK_RBUTTON ) < 0;
33728 Self_.fRightClick := True;
33729 end;
33730 NM_CLICK:
33731 begin
33732 Self_.fCurItem := -1; // return CurItem = -1
33733 Self_.fCurIndex := -1;
33734 Self_.fRightClick := False;
33735 Result := Notify.iItem <> -1;
33736 // do not handle - if it will be handled in WM_COMMAND
33737 Exit;
33738 end;
33739 TBN_DROPDOWN:
33740 begin
33741 Self_.fCurItem := Notify.iItem;
33742 Self_.fCurIndex := Self_.TBItem2Index( Self_.fCurItem );
33743 if assigned( Self_.fOnDropDown ) then
33744 Self_.fOnDropDown( Self_ );
33745 end;
33746 end;
33747 end;
33748 end;
33749 {$ENDIF ASM_VERSION}
33750 //[END WndProcToolbarCtr]
33752 const ToolbarAligns: array[ TControlAlign ] of DWORD =
33753 ( CCS_NOPARENTALIGN {or CCS_NOMOVEY} {or CCS_NORESIZE} or CCS_NODIVIDER, CCS_TOP or CCS_VERT, CCS_TOP, CCS_BOTTOM or CCS_VERT, CCS_BOTTOM,
33754 CCS_TOP );
33755 ToolbarOptions: array[ TToolbarOption ] of Integer = ( TBSTYLE_LIST, not TBSTYLE_LIST,
33756 TBSTYLE_FLAT, TBSTYLE_TRANSPARENT, TBSTYLE_WRAPABLE, CCS_NODIVIDER, 0 );
33758 {$IFDEF USE_CONSTRUCTORS}
33759 //[function NewToolbar]
33760 function NewToolbar( AParent: PControl; Align: TControlAlign; Options: TToolbarOptions;
33761 Bitmap: HBitmap; Buttons: array of PChar;
33762 BtnImgIdxArray: array of Integer ) : PControl;
33763 begin
33764 new( Result, CreateToolbar( AParent, Align, Options, Bitmap, Buttons, BtnImgIdxArray ) );
33765 end;
33766 //[END NewToolbar]
33767 {$ELSE not_USE_CONSTRUCTORS}
33769 //[FUNCTION NewToolbar]
33770 {$IFDEF ASM_!VERSION}
33771 function NewToolbar( AParent: PControl; Align: TControlAlign; Options: TToolbarOptions;
33772 Bitmap: HBitmap; Buttons: array of PChar;
33773 BtnImgIdxArray: array of Integer ) : PControl;
33774 const szTBButton = Sizeof( TTBButton );
33775 Option3DBorder = 1 shl Ord( tbo3DBorder );
33777 MOVZX EDX, DL
33778 PUSH EDX // Align
33779 PUSH EAX // AParent
33781 XOR EAX, EAX
33782 TEST CL, Option3DBorder
33783 SETNZ AL
33784 PUSH EAX
33786 PUSH ECX // Options
33788 MOV AL, ICC_BAR_CLASSES
33789 CALL DoInitCommonControls
33791 MOV EAX, ESP
33792 MOV EDX, offset[ToolbarOptions]
33793 XOR ECX, ECX
33794 MOV CL, 5
33795 CALL MakeFlags
33796 POP EDX
33798 PUSH 0
33799 XCHG ECX, EAX // ECX = MakeFlags(...)
33800 MOV EAX, [ESP+8] // EAX = AParent
33801 MOV EDX, [ESP+12] // EDX = Align
33802 OR ECX, [EDX*4+offset ToolbarAligns]
33803 OR ECX, WS_CHILD or WS_VISIBLE or TBSTYLE_TOOLTIPS
33804 MOV EDX, offset[ TOOLBARCLASSNAME ]
33805 CALL _NewCommonControl
33806 MOV [EAX].TControl.fCommandActions.aClear, offset[ClearToolbar]
33807 MOV [EAX].TControl.fCommandActions.aGetCount, TB_BUTTONCOUNT
33808 INC [EAX].TControl.fIsButton
33809 POP EDX // pop AParent
33810 POP EDX // EDX = Align
33811 PUSH EDX
33812 TEST EDX, EDX
33813 JE @@zero_bounds
33814 ADD [EAX].TControl.fBoundsRect.Bottom, 26-64
33815 ADD [EAX].TControl.fBoundsRect.Right, 1000-64
33816 JMP @@bounds_ready
33817 @@zero_bounds:
33818 MOV [EAX].TControl.fBoundsRect.Left, EDX
33819 MOV [EAX].TControl.fBoundsRect.Top, EDX
33820 MOV [EAX].TControl.fBoundsRect.Right, EDX
33821 MOV [EAX].TControl.fBoundsRect.Bottom, EDX
33822 @@bounds_ready:
33823 PUSH EBX
33824 PUSH ESI
33825 XCHG EBX, EAX
33826 MOV ESI, offset[TControl.Perform]
33827 PUSH 0
33828 PUSH 0
33829 PUSH TB_GETEXTENDEDSTYLE
33830 PUSH EBX
33831 CALL ESI
33832 OR EAX, TBSTYLE_EX_DRAWDDARROWS
33833 PUSH EAX
33834 PUSH 0
33835 PUSH TB_SETEXTENDEDSTYLE
33836 PUSH EBX
33837 CALL ESI
33838 MOV EDX, offset[WndProcToolbarCtrl]
33839 MOV EAX, EBX
33840 CALL TControl.AttachProc
33841 MOV EDX, offset[WndProcDoEraseBkgnd]
33842 MOV EAX, EBX
33843 CALL TControl.AttachProc
33844 PUSH 0
33845 PUSH szTBButton
33846 PUSH TB_BUTTONSTRUCTSIZE
33847 PUSH EBX
33848 CALL ESI
33849 PUSH 0
33850 PUSH [EBX].TControl.fMargin
33851 PUSH TB_SETINDENT
33852 PUSH EBX
33853 CALL ESI
33854 MOV EAX, [ESP+8] // Align
33855 {$IFDEF PARANOIA}
33856 DB $2C, 1
33857 {$ELSE}
33858 SUB AL, 1
33859 {$ENDIF}
33860 JL @@bounds_correct
33861 JE @@corr_right
33862 {$IFDEF PARANOIA}
33863 DB $2C, 2
33864 {$ELSE}
33865 SUB AL, 2
33866 {$ENDIF}
33867 JNE @@corr_bottom
33868 @@corr_right:
33869 MOV EDX, [EBX].TControl.fBoundsRect.Left
33870 ADD EDX, 24
33871 MOV [EBX].TControl.fBoundsRect.Right, EDX
33872 JMP @@bounds_correct
33873 @@corr_bottom:
33874 MOV EDX, [EBX].TControl.fBoundsRect.Top
33875 ADD EDX, 22
33876 MOV [EBX].TControl.fBoundsrect.Bottom, EDX
33877 @@bounds_correct:
33878 MOV EDX, [Bitmap]
33879 TEST EDX, EDX
33880 JZ @@bitmap_added
33881 MOV EAX, EBX
33882 CALL TControl.TBAddBitmap
33883 @@bitmap_added:
33885 PUSH dword ptr [BtnImgIdxArray]
33886 PUSH dword ptr [BtnImgIdxArray-4]
33887 MOV ECX, [Buttons-4]
33888 MOV EDX, [Buttons]
33889 MOV EAX, EBX
33890 CALL TControl.TBAddButtons
33892 PUSH 0
33893 PUSH 0
33894 PUSH WM_SIZE
33895 PUSH EBX
33896 CALL ESI
33898 XCHG EAX, EBX
33899 POP ESI
33900 POP EBX
33901 ///POP EDX ///!!! next command is MOV ESP,EBP
33902 end;
33903 {$ELSE ASM_VERSION} //Pascal
33904 function NewToolbar( AParent: PControl; Align: TControlAlign; Options: TToolbarOptions;
33905 Bitmap: HBitmap; Buttons: array of PChar;
33906 BtnImgIdxArray: array of Integer ) : PControl;
33907 var Flags: DWORD;
33908 begin
33909 if not( tboTextBottom in Options ) then
33910 Options := Options + [ tboTextRight ];
33911 if tboTextRight in Options then
33912 Options := Options - [ tboTextBottom ];
33913 Flags := MakeFlags( @Options, ToolbarOptions );
33914 DoInitCommonControls( ICC_BAR_CLASSES );
33915 Result := _NewCommonControl( AParent, TOOLBARCLASSNAME,
33916 (ToolbarAligns[ Align ] or WS_CHILD or WS_VISIBLE or TBSTYLE_TOOLTIPS or Flags),
33917 //(not (Align in [caNone])) and not (tboNoDivider in Options), nil );
33918 tbo3DBorder in Options, nil );
33919 Result.fCommandActions.aClear := ClearToolbar;
33920 Result.fCommandActions.aGetCount := TB_BUTTONCOUNT;
33921 Result.fIsButton := TRUE;
33922 with Result.fBoundsRect do
33923 begin
33924 if Align in [ caNone ] then
33925 begin
33926 Bottom := Top + 26;
33927 Right := Left + 1000;
33929 else
33930 begin
33931 Left := 0; Right := 0;
33932 Top := 0; Bottom := 0;
33933 end;
33934 end;
33935 Result.AttachProc( WndProcToolbarCtrl );
33936 Result.AttachProc( WndProcDoEraseBkgnd );
33937 Result.Perform(TB_SETEXTENDEDSTYLE, 0, Result.Perform(TB_GETEXTENDEDSTYLE, 0, 0) or
33938 TBSTYLE_EX_DRAWDDARROWS);
33940 Result.Perform( TB_BUTTONSTRUCTSIZE, Sizeof( TTBButton ), 0 );
33941 Result.Perform( TB_SETINDENT, Result.fMargin, 0 );
33942 with Result.fBoundsRect do
33943 begin
33944 if Align in [ caLeft, caRight ] then
33945 Right := Left + 24
33946 else if not (Align in [caNone]) then
33947 Bottom := Top + 22;
33948 end;
33949 if Bitmap <> 0 then
33950 Result.TBAddBitmap( Bitmap );
33951 Result.TBAddButtons( Buttons, BtnImgIdxArray );
33952 Result.Perform( WM_SIZE, 0, 0 );
33953 end;
33954 {$ENDIF ASM_VERSION}
33955 //[END NewToolbar]
33957 {$ENDIF USE_CONSTRUCTORS}
33959 //================== DateTimePicker =====================//
33961 function WndProcDateTimePickerNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
33962 var NMhdr: PNMHdr;
33963 D: TDateTime;
33964 AllowChg: Boolean;
33965 NMDTString: PNMDateTimeString;
33966 begin
33967 Result := False;
33968 if Msg.message = WM_NOTIFY then
33969 begin
33970 NMHdr := Pointer( Msg.lParam );
33971 CASE NMHdr.code OF
33972 DTN_DROPDOWN: if Assigned( Self_.fOnDropDown ) then
33973 Self_.fOnDropDown( Self_ );
33974 DTN_CLOSEUP: if Assigned( Self_.fOnCloseUp ) then
33975 Self_.fOnCloseUp( Self_ );
33976 DTN_DATETIMECHANGE:
33977 if Assigned( Self_.fOnChange ) then
33978 Self_.fOnChange( Self_ );
33979 {DTN_FORMAT:
33980 Rslt := 0;}
33981 DTN_USERSTRING:
33982 if Assigned( Self_.fOnDTPUserString ) then
33983 begin
33984 NMDTString := Pointer( NMHdr );
33985 D := 0.0;
33986 AllowChg := TRUE;
33987 Self_.fOnDTPUserString( Self_, NMDTString.pszUserString, D, AllowChg );
33988 NMDTString.dwFlags := Integer( not AllowChg );
33989 end;
33990 END;
33991 end;
33992 end;
33994 const
33995 //( dtpoTime, dtpoDateLong, dtpoUpDown, dtpoRightAlign,
33996 // dtpoShowNone, dtpoParseInput )
33998 DateTimePickerOptions: array[ TDateTimePickerOption ] of Integer = (
33999 DTS_TIMEFORMAT, DTS_LONGDATEFORMAT, DTS_UPDOWN, DTS_RIGHTALIGN,
34000 DTS_SHOWNONE, DTS_APPCANPARSE );
34002 function NewDateTimePicker( AParent: PControl; Options: TDateTimePickerOptions )
34003 : PControl;
34004 var Flags: DWORD;
34005 const
34006 CS_OFF = CS_OWNDC or CS_CLASSDC or CS_PARENTDC or CS_GLOBALCLASS or
34007 CS_VREDRAW or CS_HREDRAW;
34008 begin
34009 DoInitCommonControls( ICC_DATE_CLASSES );
34010 Flags := MakeFlags( @Options, DateTimePickerOptions );
34011 Result := _NewCommonControl( AParent, DATETIMEPICK_CLASS,
34012 (WS_CHILD or WS_VISIBLE or WS_TABSTOP or Flags), TRUE, nil );
34013 //Result.ClsStyle := Result.ClsStyle and not CS_OFF;
34014 Result.SetSize( 110, 24 );
34015 Result.AttachProc( WndProcDateTimePickerNotify );
34016 end;
34018 procedure TControl.SetDateTime(Value: TDateTime);
34019 var ST: TSystemTime;
34020 begin
34021 DateTime2SystemTime( Value, ST );
34022 Perform( DTM_SETSYSTEMTIME, Integer( IsNAN( Value ) ) , Integer( @ ST ) );
34023 end;
34025 function TControl.GetDateTime: TDateTime;
34026 var ST: TSystemTime;
34027 begin
34028 if Perform( DTM_GETSYSTEMTIME, 0, Integer( @ ST ) ) = GDT_VALID then
34029 SystemTime2DateTime( ST, Result )
34030 else
34031 Result := NAN;
34032 end;
34034 function TControl.GetDate: TDateTime;
34035 begin
34036 Result := DateTime;
34037 if not IsNAN( Result ) then
34038 Result := Trunc( DateTime );
34039 end;
34041 function TControl.GetTime: TDateTime;
34042 begin
34043 Result := DateTime;
34044 if not IsNAN( Result ) then
34045 Result := Frac( Result );
34046 end;
34048 procedure TControl.SetDate(const Value: TDateTime);
34049 begin
34050 if IsNAN( Value ) then
34051 DateTime := Value
34052 else
34053 if not IsNAN( DateTime ) then
34054 DateTime := Trunc( Value ) + Frac( DateTime )
34055 else
34056 DateTime := Trunc( Value );
34057 end;
34059 procedure TControl.SetTime(const Value: TDateTime);
34060 begin
34061 if IsNAN( Value ) then
34062 DateTime := Value
34063 else
34064 if not IsNAN( DateTime ) then
34065 DateTime := Trunc( DateTime ) + Frac( Value )
34066 else
34067 DateTime := 1.0 + Frac( Value );
34068 end;
34070 function TControl.GetDateTimeRange: TDateTimeRange;
34071 var ST_R: array[ 0..1 ] of TSystemTime;
34072 begin
34073 Perform( DTM_GETRANGE, 0, Integer( @ ST_R[ 0 ] ) );
34074 SystemTime2DateTime( ST_R[ 0 ], Result[ 0 ] );
34075 SystemTime2DateTime( ST_R[ 1 ], Result[ 1 ] );
34076 end;
34078 procedure TControl.SetDateTimeRange(Value: TDateTimeRange);
34079 var ST_R: array[ 0..1 ] of TSystemTime;
34080 begin
34081 DateTime2SystemTime( Value[ 0 ], ST_R[ 0 ] );
34082 DateTime2SystemTime( Value[ 1 ], ST_R[ 1 ] );
34083 Perform( DTM_SETRANGE,
34084 Integer( IsNAN( Value[ 0 ] ) ) or
34085 (Integer( IsNAN( Value[ 1 ] ) ) shl 1),
34086 Integer( @ ST_R[ 0 ] ) );
34087 end;
34089 function TControl.GetDateTimePickerColor( Index: TDateTimePickerColor): TColor;
34090 begin
34091 Result := Perform( DTM_GETMCCOLOR, Integer( Index ), 0 );
34092 end;
34094 procedure TControl.SetDateTimePickerColor(
34095 Index: TDateTimePickerColor; Value: TColor);
34096 begin
34097 Perform( DTM_SETMCCOLOR, Integer( Index ), Color2RGB( Value ) );
34098 end;
34100 procedure TControl.SetDateTimeFormat(const Value: String);
34101 begin
34102 Perform( DTM_SETFORMAT, 0, Integer( PChar( Value ) ) );
34103 end;
34105 function MakeDateTimeRange( D1, D2: TDateTime ): TDateTimeRange;
34106 begin
34107 Result[ 0 ] := D1;
34108 Result[ 1 ] := D2;
34109 end;
34112 //===================== RichEdit ========================//
34114 type PENLink = ^TENLink;
34115 TENLink = packed record
34116 hdr: TNMHDR;
34117 msg: DWORD;
34118 wParam: Integer;
34119 lParam: Integer;
34120 chrg: TCHARRANGE;
34121 end;
34122 TEXTRANGEA = packed record
34123 chrg: TCharRange;
34124 lpstrText: PAnsiChar;
34125 end;
34127 //[FUNCTION WndProc_RE_LinkNotify]
34128 {$IFDEF ASM_VERSION}
34129 function WndProc_RE_LinkNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
34131 CMP word ptr [EDX].TMsg.message, WM_NOTIFY
34132 JNE @@ret_false
34133 MOV EDX, [EDX].TMsg.lParam
34134 CMP [EDX].TNMHdr.code, EN_LINK
34135 JNE @@ret_false
34136 PUSH EBX
34137 PUSH EDX
34138 XCHG EBX, EAX
34139 XOR EAX, EAX
34140 MOV [ECX], EAX
34141 ADD ESP, -1020
34142 PUSH EAX
34143 PUSH ESP
34144 PUSH [EDX].TENLink.chrg.cpMax
34145 PUSH [EDX].TENLink.chrg.cpMin
34146 PUSH ESP
34147 PUSH 0
34148 PUSH EM_GETTEXTRANGE
34149 PUSH EBX
34150 CALL TControl.Perform
34151 ADD ESP, 12
34152 MOV EDX, ESP
34153 LEA EAX, [EBX].TControl.fREUrl
34154 CALL System.@LStrFromPChar
34155 ADD ESP, 1024
34156 POP EDX
34157 MOV ECX, [EDX].TENLink.msg
34158 LEA EAX, [EBX].TControl.fOnREOverURL
34159 CMP ECX, WM_MOUSEMOVE
34160 JE @@Url_event
34161 LEA EAX, [EBX].TControl.fOnREUrlClick
34162 CMP ECX, WM_LBUTTONDOWN
34163 JE @@Url_Event
34164 CMP ECX, WM_RBUTTONDOWN
34165 JNE @@after_Url_event
34166 @@Url_event:
34167 MOV ECX, [EAX].TMethod.Code
34168 JECXZ @@after_Url_event
34169 MOV EDX, EBX
34170 MOV EAX, [EAX].TMethod.Data
34171 CALL ECX
34172 @@after_Url_event:
34173 POP EBX
34174 MOV AL, 1
34176 @@ret_false:
34177 XOR EAX, EAX
34178 end;
34179 {$ELSE ASM_VERSION} //Pascal
34180 function WndProc_RE_LinkNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
34181 var Link: PENLink;
34182 Range: TextRangeA;
34183 Buffer: array[ 0..1023 ] of Char;
34184 begin
34185 Result := False;
34186 if (Msg.message = WM_NOTIFY) and (PNMHdr( Msg.lParam ).code = EN_LINK) then
34187 begin
34188 Link := Pointer( Msg.lParam );
34189 Range.chrg := Link.chrg;
34190 Range.lpstrText := @Buffer[ 0 ]; //Pchar( @Buffer[ 0 ] );
34191 Buffer[ 0 ] := #0;
34192 Self_.Perform( EM_GETTEXTRANGE, 0, Integer( @Range ) );
34193 Self_.fREUrl := Buffer;
34194 case Link.msg of
34195 WM_MOUSEMOVE:
34196 if assigned( Self_.fOnREOverURL ) then
34197 Self_.fOnREOverURL( Self_ );
34198 WM_LBUTTONDOWN, WM_RBUTTONDOWN:
34199 if assigned( Self_.fOnREUrlClick ) then
34200 Self_.fOnREUrlClick( Self_ );
34201 end;
34202 Rslt := 0;
34203 Result := TRUE;
34204 end;
34205 end;
34206 {$ENDIF ASM_VERSION}
34207 //[END WndProc_RE_LinkNotify]
34209 var Global_DisableParentCursor: Boolean;
34211 //[FUNCTION WndProcRichEditNotify]
34212 {$IFDEF ASM_noVERSION}
34213 function WndProcRichEditNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
34214 const int_IDC_ARROW = integer( IDC_ARROW );
34216 CMP word ptr [EDX].TMsg.message, WM_NOTIFY
34217 JNE @@ret_false {YS}
34218 // JNE @@chk_WM_SETCURSOR {YS}
34219 MOV EDX, [EDX].TMsg.lParam
34220 CMP [EDX].TNMHdr.code, EN_SELCHANGE
34221 JNE @@ret_false
34222 //PUSH EAX
34223 CALL TControl.DoSelChange
34224 //POP EAX
34225 {CMP [EAX].TControl.fTransparent, 0
34226 JZ @@ret_false
34227 CALL TControl.Invalidate}
34228 @@ret_false:
34229 XOR EAX, EAX
34231 { //YS
34232 @@chk_WM_SETCURSOR:
34233 CMP word ptr [EDX].TMsg.message, WM_SETCURSOR
34234 JNE @@ret_false
34235 PUSH EBX
34236 MOV EBX, EAX
34237 PUSH ECX
34238 PUSH EDX
34239 INC [Global_DisableParentCursor]
34240 CALL TControl.CallDefWndProc
34241 DEC [Global_DisableParentCursor]
34242 POP EDX
34243 MOVZX EDX, word ptr [EDX].TMsg.lParam
34244 POP ECX
34245 MOV [ECX], EAX
34246 TEST EAX, EAX
34247 MOV EAX, [EBX].TControl.fCursor
34248 POP EBX
34249 JNZ @@ret_true
34250 INC dword ptr [ECX]
34251 CMP EDX, HTCLIENT
34252 JE @@set_cursor
34253 CMP EDX, HTVSCROLL
34254 JE @@set_arrow_cursor
34255 CMP EDX, HTHSCROLL
34256 JNE @@ret_false
34257 @@set_arrow_cursor:
34258 PUSH int_IDC_ARROW
34259 PUSH 0
34260 CALL LoadCursor
34261 @@set_cursor:
34262 PUSH EAX
34263 CALL Windows.SetCursor
34264 @@ret_true:
34265 MOV AL, 1
34267 end;
34268 {$ELSE ASM_VERSION} //Pascal
34269 function WndProcRichEditNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
34270 var NMhdr: PNMHdr;
34271 // TestCode: Integer;
34272 {FR: TFormatRange;
34273 I: Integer;
34274 R: TRect;
34275 LogX, LogY: Integer;}
34276 begin
34277 Result := False;
34278 if Msg.message = WM_NOTIFY then
34279 begin
34280 NMHdr := Pointer( Msg.lParam );
34281 case NMHdr.code of
34282 EN_SELCHANGE:
34283 begin
34284 Self_.DoSelChange;
34285 if Self_.fTransparent then
34286 Self_.Invalidate;
34287 end;
34288 end;
34290 { // YS
34291 else
34292 if Msg.message = WM_SETCURSOR then
34293 begin
34294 Result := True;
34295 TestCode := LoWord( Msg.lParam );
34296 Global_DisableParentCursor := True;
34297 Rslt := Self_.CallDefWndProc( Msg );
34298 Global_DisableParentCursor := False;
34299 if Rslt = 0 then
34300 begin
34301 Rslt := 1;
34302 case TestCode of
34303 HTVSCROLL, HTHSCROLL: Windows.SetCursor( LoadCursor( 0, IDC_ARROW ) );
34304 HTCLIENT: Windows.SetCursor( Self_.fCursor );
34305 else Result := False;
34306 end;
34307 end;
34308 end;
34310 end;
34311 {$ENDIF ASM_VERSION}
34312 //[END WndProcRichEditNotify]
34314 var FRichEditModule: Integer;
34315 RichEditClass: PChar = 'RichEdit20A';
34316 RichEditLib: PChar = 'RICHED32.DLL';
34318 const RichEditLibnames: array[ 0..2 ] of PChar =
34319 ( 'RICHED20.DLL', 'RICHED32.DLL', 'RICHED.DLL' );
34320 const RichEditflags: array [ TEditOption ] of Integer = (
34321 not (es_AutoHScroll or WS_HSCROLL),
34322 not (es_AutoVScroll or WS_VSCROLL),
34323 0 {es_Lowercase - not supported},
34324 0 {es_Multiline - RichEdit always multiline},
34325 es_NoHideSel,
34326 0 {es_OemConvert - not suppoted},
34327 0 {es_Password - not supported},
34328 es_Readonly,
34329 0 {es_UpperCase - not supported},
34330 es_WantReturn, 0, es_Number );
34332 {$IFDEF USE_CONSTRUCTORS}
34333 //[function NewRichEdit1]
34334 function NewRichEdit1( AParent: PControl; Options: TEditOptions ): PControl;
34335 begin
34336 new( Result, CreateRichEdit1( AParent, Options ) );
34337 end;
34338 //[END NewRichEdit1]
34339 {$ELSE not_USE_CONSTRUCTORS}
34341 //[FUNCTION NewRichEdit1]
34342 {$IFDEF ASM_VERSION}
34343 const RichEditClass10: array[0..8] of Char = ('R','i','c','h','E','d','i','t',#0);
34344 function NewRichEdit1( AParent: PControl; Options: TEditOptions ): PControl;
34346 PUSH EDX
34348 MOV ECX, [FRichEditModule]
34349 INC ECX
34350 LOOP @@loaded
34351 PUSHAD
34352 MOV BL, 3
34353 LEA ESI, [RichEditLibNames]
34354 @@loo:
34355 LODSD
34356 PUSH EAX
34357 CALL LoadLibrary
34358 CMP EAX, HINSTANCE_ERROR
34359 JG @@break
34360 MOV [RichEditClass], offset[RichEditClass10]
34361 DEC BL
34362 JNZ @@loo
34363 JMP @@fault
34364 @@break:
34365 MOV [FRichEditModule], EAX
34366 @@fault:
34367 POPAD
34368 @@loaded:
34369 PUSH EAX
34370 PUSH EDX
34371 MOV EAX, ESP
34372 MOV EDX, offset[RichEditFlags]
34373 XOR ECX, ECX
34374 MOV CL, 10
34375 CALL MakeFlags
34376 XCHG ECX, EAX
34377 POP EDX
34378 POP EAX
34379 PUSH 1
34380 PUSH offset[RichEditActions]
34381 MOV EDX, [RichEditClass]
34382 OR ECX, WS_VISIBLE or WS_CHILD or WS_TABSTOP or WS_BORDER or ES_MULTILINE
34383 CALL _NewCommonControl
34384 INC [EAX].TControl.fIgnoreDefault
34385 POP EDX
34386 TEST DH, 4 // is eoWantTab in Options ?
34387 SETZ DL
34388 MOV [EAX].TControl.fLookTabKeys, DL
34389 PUSH EBX
34390 MOV EBX, EAX
34391 MOV EDX, offset[WndProcRichEditNotify]
34392 CALL TControl.AttachProc
34393 MOV [EBX].TControl.fDoubleBuffered, 0
34394 INC [EBX].TControl.fCannotDoubleBuf
34395 ADD [EBX].TControl.fBoundsRect.Right, 100-64
34396 ADD [EBX].TControl.fBoundsRect.Bottom, 200-64
34397 PUSH ENM_CHANGE or ENM_SELCHANGE or ENM_REQUESTRESIZE or ENM_PROTECTED or $04000000
34398 PUSH 0
34399 PUSH EM_SETEVENTMASK
34400 PUSH EBX
34401 CALL TControl.Perform
34402 MOV EAX, clWindow
34403 MOV [EBX].TControl.fColor, EAX
34404 CALL Color2RGB
34405 PUSH EAX
34406 PUSH 0
34407 PUSH EM_SETBKGNDCOLOR
34408 PUSH EBX
34409 CALL TControl.Perform
34410 XCHG EAX, EBX
34411 POP EBX
34412 end;
34413 {$ELSE ASM_VERSION} //Pascal
34414 function NewRichEdit1( AParent: PControl; Options: TEditOptions ): PControl;
34415 var Flags, I: Integer;
34416 begin
34417 if FRichEditModule = 0 then
34418 begin
34419 for I := 0 to 2 do
34420 begin
34421 FRichEditModule := LoadLibrary( RichEditLibnames[ I ] );
34422 if FRichEditModule > HINSTANCE_ERROR then break;
34423 RichEditClass := 'RichEdit';
34424 end;
34425 if FRichEditModule <= HINSTANCE_ERROR then
34426 FRichEditModule := 0;
34427 end;
34428 Flags := MakeFlags( @Options, RichEditFlags );
34429 Result := _NewCommonControl( AParent, RichEditClass, WS_VISIBLE or WS_CHILD
34430 or WS_TABSTOP or WS_BORDER or ES_MULTILINE or Flags,
34431 True, @RichEditActions );
34432 Result.fIgnoreDefault := TRUE;
34433 Result.fLookTabKeys := [ tkTab ];
34434 if eoWantTab in Options then
34435 Result.fLookTabKeys := [ ];
34437 Result.AttachProc( WndProcRichEditNotify );
34438 Result.fDoubleBuffered := False;
34439 Result.fCannotDoubleBuf := True;
34440 with Result.fBoundsRect do
34441 begin
34442 Right := Right + 100;
34443 Bottom := Top + 200;
34444 end;
34445 Result.Perform( EM_SETEVENTMASK, 0,
34446 ENM_CHANGE or ENM_SELCHANGE or ENM_REQUESTRESIZE or
34447 ENM_PROTECTED or $04000000 {ENM_LINK} or ENM_KEYEVENTS {or ENM_MOUSEEVENTS} );
34448 Result.fColor := clWindow;
34449 Result.Perform( EM_SETBKGNDCOLOR, 0, Color2RGB(Result.fColor));
34450 //Result.Perform( WM_SIZE, 0, 0 );
34451 end;
34452 {$ENDIF ASM_VERSION}
34453 //[END NewRichEdit1]
34455 {$ENDIF USE_CONSTRUCTORS}
34457 //[API OleInitialize]
34458 function OleInitialize(pwReserved: Pointer): HResult; stdcall;
34459 external 'ole32.dll' name 'OleInitialize';
34460 procedure OleUninitialize; stdcall;
34461 external 'ole32.dll' name 'OleUninitialize';
34463 //[FUNCTION OleInit]
34464 {$IFDEF ASM_VERSION}
34465 function OleInit: Boolean;
34467 MOV ECX, [OleInitCount]
34468 INC ECX
34469 LOOP @@init1
34470 PUSH ECX
34471 CALL OleInitialize
34472 TEST EAX, EAX
34473 MOV AL, 0
34474 JNZ @@exit
34475 @@init1:
34476 INC [OleInitCount]
34477 MOV AL, 1
34478 @@exit:
34479 end;
34480 {$ELSE ASM_VERSION} //Pascal
34481 function OleInit: Boolean;
34482 begin
34483 if OleInitCount = 0 then
34484 begin
34485 Result := False;
34486 if OleInitialize( nil ) <> 0 then Exit;
34487 end;
34488 Inc( OleInitCount );
34489 Result := True;
34490 end;
34491 {$ENDIF ASM_VERSION}
34492 //[END OleInit]
34494 //[PROCEDURE OleUnInit]
34495 {$IFDEF ASM_VERSION}
34496 procedure OleUnInit;
34498 MOV ECX, [OleInitCount]
34499 JECXZ @@exit
34500 DEC [OleInitCount]
34501 JNZ @@exit
34502 CALL OleUninitialize
34503 @@exit:
34504 end;
34505 {$ELSE ASM_VERSION} //Pascal
34506 procedure OleUnInit;
34507 begin
34508 if OleInitCount > 0 then
34509 begin
34510 Dec( OleInitCount );
34511 if OleInitCount = 0 then
34512 OleUninitialize;
34513 end;
34514 end;
34515 {$ENDIF ASM_VERSION}
34516 //[END OleUnInit]
34518 //[API SysAllocStringLen]
34519 function SysAllocStringLen;
34520 external 'oleaut32.dll' name 'SysAllocStringLen';
34521 procedure SysFreeString( psz: PWideChar ); stdcall;
34522 external 'oleaut32.dll' name 'SysFreeString';
34525 //[function StringToOleStr]
34526 function StringToOleStr(const Source: string): PWideChar;
34528 SourceLen, ResultLen: Integer;
34529 Buffer: array[0..1023] of WideChar;
34530 begin
34531 SourceLen := Length(Source);
34532 if Length(Source) < SizeOf(Buffer) div 2 then
34533 Result := SysAllocStringLen(Buffer, MultiByteToWideChar(0, 0,
34534 PChar(Source), SourceLen, Buffer, SizeOf(Buffer) div 2))
34535 else
34536 begin
34537 ResultLen := MultiByteToWideChar(0, 0,
34538 Pointer(Source), SourceLen, nil, 0);
34539 Result := SysAllocStringLen(nil, ResultLen);
34540 MultiByteToWideChar(0, 0, Pointer(Source), SourceLen,
34541 Result, ResultLen);
34542 end;
34543 end;
34546 {$IFDEF USE_CONSTRUCTORS}
34547 //[function NewRichEdit]
34548 function NewRichEdit( AParent: PControl; Options: TEditOptions ): PControl;
34549 begin
34550 new( Result, CreateRichEdit( AParent, Options ) );
34551 end;
34552 //[END NewRichEdit]
34553 {$ELSE not_USE_CONSTRUCTORS}
34555 //[FUNCTION NewRichEdit]
34556 {$IFDEF ASM_VERSION}
34557 const RichEdit20A: array[0..11] of Char = ('R','i','c','h','E','d','i','t','2','0','A',#0 );
34558 RichEd20_DLL: array[ 0..12] of Char = ('R','I','C','H','E','D','2','0','.','D','L','L',#0 );
34559 function NewRichEdit( AParent: PControl; Options: TEditOptions ): PControl;
34560 const deltaChr = 24; // sizeof( TCharFormat2 ) - sizeof( RichEdit.TCharFormat );
34561 deltaPar = sizeof( TParaFormat2 ) - sizeof( RichEdit.TParaFormat );
34563 PUSHAD
34564 CALL OleInit
34565 TEST EAX, EAX
34566 POPAD
34567 JZ @@new1
34568 PUSH [RichEditClass]
34569 MOV [RichEditClass], offset[RichEdit20A]
34570 PUSH [RichEditLib]
34571 MOV [RichEditLib], offset[RichEd20_DLL]
34572 CALL NewRichEdit1
34573 POP [RichEditLib]
34574 POP [RichEditClass]
34575 MOV byte ptr [EAX].TControl.fCharFmtDeltaSz, deltaChr
34576 MOV byte ptr [EAX].TControl.fParaFmtDeltaSz, deltaPar
34578 @@new1: CALL NewRichEdit1
34579 end;
34580 {$ELSE ASM_VERSION} //Pascal
34581 function NewRichEdit( AParent: PControl; Options: TEditOptions ): PControl;
34582 var OldRichEditClass, OldRichEditLib: PChar;
34583 begin
34584 if OleInit then
34585 begin
34586 OldRichEditClass := RichEditClass;
34587 RichEditClass := 'RichEdit20A';
34588 OldRichEditLib := RichEditLib;
34589 RichEditLib := 'RICHED20.DLL';
34590 Result := NewRichEdit1( AParent, Options );
34591 Result.fCharFmtDeltaSz := 24; //sizeof( TCharFormat2 ) - sizeof( RichEdit.TCharFormat );
34592 // sizeof( TCharFormat2 ) is calculated incorrectly
34593 Result.fParaFmtDeltaSz := sizeof( TParaFormat2 ) - sizeof( RichEdit.TParaFormat );
34594 RichEditClass := OldRichEditClass;
34595 RichEditLib := OldRichEditLib;
34597 else
34598 Result := NewRichEdit1( AParent, Options );
34599 end;
34600 {$ENDIF ASM_VERSION}
34601 //[END NewRichEdit]
34603 {$ENDIF USE_CONSTRUCTORS}
34605 //=====================================================================//
34626 { TControl }
34628 {$IFDEF ASM_VERSION}
34629 //[procedure TControl.Init]
34630 procedure TControl.Init;
34631 const
34632 IniStyle = WS_VISIBLE or WS_CLIPCHILDREN or WS_CLIPSIBLINGS or
34633 WS_CAPTION or WS_SYSMENU or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or
34634 WS_BORDER or WS_THICKFRAME;
34635 asm //cmd //opd
34636 PUSH EBX
34637 MOV EBX, EAX
34638 CALL TObj.Init
34639 MOV EDX, offset WndProcDummy
34640 MOV [EBX].fOnDynHandlers, EDX
34641 MOV [EBX].fWndProcKeybd, EDX
34642 MOV [EBX].fWndProcResizeFlicks, EDX
34643 MOV [EBX].fPass2DefProc, EDX
34644 //**** MOV [EBX].fDefWndProc, offset DefWindowProc
34645 MOV [EBX].fWndFunc, offset WndFunc
34646 MOV EDX, offset ClearText
34647 MOV [EBX].fCommandActions.aClear, EDX
34648 INC dword ptr [EBX].fWindowed
34649 MOV EDX, offset DummyObjProc
34650 MOV [EBX].fControlClick, EDX
34651 MOV EDX, clBtnFace
34652 MOV [EBX].fColor, EDX
34653 MOV DL, clWindowText and $FF
34654 MOV [EBX].fTextColor, EDX
34655 MOV byte ptr [EBX].fMargin, 2
34656 INC dword ptr [EBX].fCtl3D
34657 INC dword ptr [EBX].fCtl3Dchild
34658 DEC byte ptr [EBX].fAlphaBlend
34659 CALL NewList
34660 MOV [EBX].fChildren, EAX
34661 MOV byte ptr[EBX].fClsStyle, CS_OWNDC
34662 MOV [EBX].fStyle, IniStyle
34663 INC dword ptr[EBX].fExStyle+2
34664 INC dword ptr[EBX].fVisible
34665 INC dword ptr[EBX].fEnabled
34666 CALL NewList
34667 MOV [EBX].fDynHandlers, EAX
34668 POP EBX
34669 end;
34670 {$ELSE ASM_VERSION} //Pascal
34671 procedure TControl.Init;
34672 begin
34673 inherited;
34674 fOnDynHandlers := WndProcDummy;
34675 fWndProcKeybd := WndProcDummy;
34676 fWndProcResizeFlicks := WndProcDummy;
34677 fPass2DefProc := WndProcDummy;
34678 //**** fDefWndProc := @DefWindowProc;
34679 fWndFunc := @ WndFunc;
34680 fCommandActions.aClear := ClearText;
34681 fWindowed := True;
34682 fControlClick := DummyObjProc;
34683 fColor := clBtnFace;
34684 fTextColor := clWindowText;
34685 fMargin := 2;
34686 fCtl3D := True;
34687 fCtl3Dchild := True;
34688 fAlphaBlend := 255;
34689 fChildren := NewList;
34690 fClsStyle := CS_OWNDC;
34691 fStyle := WS_VISIBLE or WS_CLIPCHILDREN or WS_CLIPSIBLINGS or
34692 WS_CAPTION or WS_SYSMENU or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or
34693 WS_BORDER or WS_THICKFRAME;
34694 fExStyle := WS_EX_CONTROLPARENT;
34695 fVisible := True;
34696 fEnabled := True;
34697 fDynHandlers := NewList;
34698 end;
34699 {$ENDIF ASM_VERSION}
34701 {$IFDEF ASM_VERSION}
34702 //[PROCEDURE CallTControlInit]
34703 procedure CallTControlInit( Ctl: PControl );
34704 begin
34705 Ctl.Init;
34706 end;
34707 //[END CallTControlInit]
34709 //[procedure TControl.InitParented]
34710 procedure TControl.InitParented( AParent: PControl );
34711 const IStyle = WS_VISIBLE or WS_CLIPCHILDREN or WS_CLIPSIBLINGS or
34712 WS_CAPTION or WS_SYSMENU or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or
34713 WS_BORDER or WS_THICKFRAME;
34714 IExStyle = WS_EX_CONTROLPARENT;
34715 IClsStyle = CS_OWNDC;
34716 int_IDC_ARROW = integer( IDC_ARROW );
34718 PUSH EAX
34719 PUSH EDX
34720 CALL CallTControlInit
34721 POP EDX
34722 POP EAX
34723 TEST EDX, EDX
34724 JZ @@0
34725 MOV ECX, [EDX].fColor
34726 MOV [EAX].fColor, ECX
34727 @@0:
34728 CALL SetParent
34729 end;
34730 {$ELSE ASM_VERSION} //Pascal
34731 procedure TControl.InitParented( AParent: PControl );
34732 begin
34733 Init;
34734 if AParent <> nil then
34735 fColor := AParent.fColor;
34736 Parent := AParent;
34737 end;
34738 {$ENDIF ASM_VERSION}
34740 {$IFDEF ASM_VERSION}
34741 //[destructor TControl.Destroy]
34742 destructor TControl.Destroy;
34744 PUSH EBX
34745 MOV EBX, EAX
34746 CALL TControl.ParentForm
34747 TEST EAX, EAX
34748 JZ @@cur_ctl_removed
34749 CMP [EAX].TControl.fCurrentControl, EBX
34750 JNE @@cur_ctl_removed
34751 XOR EDX, EDX
34752 MOV [EAX].TControl.fCurrentControl, EDX
34753 @@cur_ctl_removed:
34755 MOV ECX, [EBX].fHandle
34756 JECXZ @@wndhidden
34757 PUSH SW_HIDE
34758 PUSH ECX
34759 CALL ShowWindow
34760 @@wndhidden:
34762 MOV EAX, EBX
34763 CALL Final
34764 MOV EAX, EBX
34765 CALL DestroyChildren
34767 XOR ECX, ECX
34768 CMP [EBX].fDestroying, CL
34769 JNZ @@destroyed
34771 XCHG CL, [EBX].fCtlClsNameChg
34772 JECXZ @@skip_free_clsname
34773 MOV EAX, [EBX].fControlClassName
34774 CALL System.@FreeMem
34775 @@skip_free_clsname:
34777 INC [EBX].fDestroying
34778 MOV EAX, [EBX].fFont
34779 CALL TObj.Free
34780 MOV EAX, [EBX].fBrush
34781 CALL TObj.Free
34782 MOV EAX, [EBX].fCanvas
34783 CALL TObj.Free
34785 XOR ECX, ECX
34787 MOV [EBX].fFont, ECX // +YS
34788 MOV [EBX].fBrush, ECX // +YS
34789 MOV [EBX].fCanvas, ECX // +YS
34791 XCHG ECX, [EBX].fCustomData
34792 JECXZ @@custfree
34793 XCHG EAX, ECX
34794 CALL System.@FreeMem
34795 @@custfree:
34796 MOV EAX, [EBX].fCustomObj
34797 CALL TObj.Free
34799 MOV EAX, [EBX].fHandle
34800 TEST EAX, EAX
34801 JZ @@free_fields
34803 XOR ECX, ECX
34804 XCHG ECX, [EBX].fAccelTable
34805 JECXZ @@accelTable_destroyed
34806 PUSH ECX
34807 CALL DestroyAcceleratorTable
34808 @@accelTable_destroyed:
34809 MOV EAX, [EBX].fMenuObj
34810 CALL TObj.Free
34811 @@destroy_img_list:
34812 MOV EAX, [EBX].fImageList
34813 TEST EAX, EAX
34814 JZ @@img_list_destroyed
34815 CALL TObj.Free
34816 JMP @@destroy_img_list
34817 @@img_list_destroyed:
34819 PUSH [EBX].fHandle
34820 CALL IsWindow
34821 TEST EAX, EAX
34822 JZ @@destroy2
34824 PUSH EAX
34825 PUSH 1
34826 PUSH WM_SETICON
34827 PUSH [EBX].fHandle
34828 CALL SendMessage
34829 TEST EAX, EAX
34830 JZ @@icoremoved
34831 CMP [EBX].fIconShared, 0
34832 JNZ @@icoremoved
34833 PUSH EAX
34834 CALL DestroyIcon
34835 @@icoremoved:
34836 //********************************************************** Remarked By M.Gerasimov
34837 // PUSH offset[ID_SELF]
34838 // PUSH [EBX].fHandle
34839 // CALL RemoveProp
34840 //********************************************************** Remarked By M.Gerasimov
34841 CMP [EBX].fNCDestroyed, 0
34842 JNZ @@destroy2
34843 PUSH [EBX].fHandle
34844 CALL DestroyWindow
34845 @@destroy2:
34846 XOR EAX, EAX
34847 MOV [EBX].fHandle, EAX
34849 @@free_fields:
34850 MOV EAX, [EBX].fCaption
34851 TEST EAX, EAX
34852 JZ @@caption_freed
34853 CALL System.@FreeMem
34854 @@caption_freed:
34855 MOV EAX, [EBX].fStatusTxt
34856 TEST EAX, EAX
34857 JZ @@statusTxt_freed
34858 CALL System.@FreeMem
34859 @@statusTxt_freed:
34860 MOV ECX, [EBX].fParent
34861 JECXZ @@removed_from_parent
34862 CMP [ECX].fCurrentControl, EBX
34863 JNE @@removefromParent
34864 XOR EAX, EAX
34865 MOV [ECX].fCurrentControl, EAX
34866 @@removefromParent:
34867 MOV EAX, [ECX].fChildren
34868 //PUSH EAX
34869 MOV EDX, EBX
34870 {CALL TList.IndexOf
34871 TEST EAX, EAX
34872 POP EDX
34873 JL @@removed_from_parent
34874 XCHG EAX, EDX
34875 CALL TList.Delete}
34876 CALL TList.Remove
34877 @@removed_from_parent:
34878 MOV ECX, [EBX].fTmpBrush
34879 JECXZ @@tmpBrush_deleted
34880 PUSH ECX
34881 CALL DeleteObject
34882 @@tmpBrush_deleted:
34884 PUSH EBX
34885 PUSH [EBX].fChildren
34886 PUSH [EBX].fTBttCmd
34887 PUSH [EBX].fTBttTxt
34888 PUSH [EBX].fTmpFont
34889 PUSH [EBX].fDynHandlers
34890 MOV BL, 5
34891 @@freeloo:
34892 POP EAX
34893 CALL TObj.Free
34894 DEC BL
34895 JNZ @@freeloo
34896 POP EBX
34897 LEA EAX, [EBX].fREUrl
34898 CALL System.@LStrClr
34899 XCHG EAX, EBX
34900 CALL TObj.Destroy
34901 @@destroyed:
34902 POP EBX
34903 end;
34904 {$ELSE ASM_VERSION} //Pascal
34905 destructor TControl.Destroy;
34906 var I: Integer;
34907 F: PControl;
34908 Ico: HIcon;
34909 begin
34910 {$IFDEF USE_MHTOOLTIP}
34911 {$DEFINE destroy}
34912 {$I KOLMHToolTip}
34913 {$UNDEF destroy}
34914 {$ENDIF USE_MHTOOLTIP}
34915 F := ParentForm; // or Applet - for form ???
34916 if F <> nil then
34917 if F.FCurrentControl = @Self then
34918 F.FCurrentControl := nil;
34920 if FHandle <> 0 then
34921 ShowWindow( fHandle, SW_HIDE );
34923 Final;
34924 DestroyChildren;
34926 if not fDestroying then
34927 begin
34928 fDestroying := True;
34930 if fCtlClsNameChg then
34931 begin
34932 FreeMem( fControlClassName );
34933 fCtlClsNameChg := FALSE;
34934 end;
34936 fFont.Free;
34937 fFont := nil;
34938 fBrush.Free;
34939 fBrush := nil;
34940 fCanvas.Free;
34941 fCanvas := nil;
34943 if fCustomData <> nil then
34944 FreeMem( fCustomData );
34945 fCustomData := nil;
34946 fCustomObj.Free;
34947 fCustomObj := nil;
34949 if fHandle <> 0 then
34950 begin
34951 {$IFNDEF NEW_MENU_ACCELL}
34952 if fAccelTable <> 0 then
34953 begin
34954 DestroyAcceleratorTable( fAccelTable );
34955 fAccelTable := 0;
34956 end;
34957 {$ENDIF}
34958 fMenuObj.Free;
34959 while fImageList <> nil do
34960 fImageList.Free;
34961 I := fHandle;
34962 if IsWindow( I ) then
34963 begin
34964 Ico := SendMessage( I, WM_SETICON, 1, 0 );
34965 if Ico <> 0 then
34966 if not fIconShared then
34967 DestroyIcon( Ico );
34968 //********************************************************** Remarked By M.Gerasimov
34969 // RemoveProp( I, ID_SELF );
34970 //********************************************************** Remarked By M.Gerasimov
34971 if not fNCDestroyed then
34972 begin
34973 {$IFDEF DEBUG_ENDSESSION}
34974 if EndSession_Initiated then
34975 LogFileOutput( GetStartDir + 'es_debug.txt',
34976 'DESTROYING HWND:' + Int2Str( I ) );
34977 {$ENDIF}
34978 DestroyWindow( I );
34979 end;
34981 {$IFDEF TEST_CLOSE}
34982 else
34984 int 3
34985 end;
34986 {$ENDIF}
34988 fHandle := 0;
34989 end;
34991 if fTmpBrush <> 0 then
34992 DeleteObject( fTmpBrush );
34993 fTmpBrush := 0;
34995 if FCaption <> nil then
34996 FreeMem( FCaption );
34997 if fStatusTxt <> nil then
34998 FreeMem( fStatusTxt );
35000 if fParent <> nil then
35001 begin
35002 {I := fParent.fChildren.IndexOf( @Self );
35003 if I >= 0 then
35004 fParent.fChildren.Delete( I );}
35005 fParent.fChildren.Remove( @Self );
35006 if fParent.fCurrentControl = @Self then
35007 fParent.fCurrentControl := nil;
35008 end;
35010 fChildren.Free;
35011 fTBttCmd.Free;
35012 fTBttTxt.Free;
35013 fTmpFont.Free;
35014 fDynHandlers.Free;
35015 fREUrl := '';
35016 inherited;
35017 end;
35018 end;
35019 {$ENDIF ASM_VERSION}
35021 {$IFDEF USE_MHTOOLTIP}
35022 {$DEFINE code}
35023 {$I KOLMHToolTip}
35024 {$UNDEF code}
35025 {$ENDIF}
35027 {$IFDEF ASM_VERSION}
35028 //[procedure TControl.SetEnabled]
35029 procedure TControl.SetEnabled( Value: Boolean );
35031 PUSH EBX
35032 MOV EBX, EAX
35033 MOVZX EDX, DL
35034 PUSH EDX
35035 CALL GetEnabled
35036 POP EDX
35037 CMP AL, DL
35038 JZ @@exit
35039 MOV [EBX].fEnabled, DL
35040 TEST EDX, EDX
35041 JNZ @@andnot
35042 OR byte ptr [EBX].fStyle + 3, 8
35043 JMP @@1
35044 @@andnot:
35045 AND byte ptr [EBX].fStyle + 3, $F7
35046 @@1:
35047 MOV ECX, [EBX].fHandle
35048 JECXZ @@exit
35050 PUSH EDX
35051 PUSH ECX
35052 CALL EnableWindow
35054 @@exit:
35055 POP EBX
35056 end;
35057 {$ELSE ASM_VERSION} //Pascal
35058 procedure TControl.SetEnabled( Value: Boolean );
35059 begin
35060 if GetEnabled = Value then Exit;
35061 fEnabled := Value;
35062 if Value then
35063 fStyle := fStyle and not WS_DISABLED
35064 else
35065 fStyle := fStyle or WS_DISABLED;
35066 if fHandle <> 0 then
35067 EnableWindow( fHandle, fEnabled );
35068 end;
35069 {$ENDIF ASM_VERSION}
35071 {$IFDEF ASM_VERSION}
35072 //[function TControl.GetParentWindow]
35073 function TControl.GetParentWindow: HWnd;
35075 MOV EAX, [EAX].fParent
35076 TEST EAX, EAX
35078 JZ @@exit
35080 CALL TControl.GetWindowHandle
35081 @@exit: --- replaced with following (6 bytes instead of 7):
35083 JNZ TControl.GetWindowHandle
35084 end;
35085 {$ELSE ASM_VERSION} //Pascal
35086 function TControl.GetParentWindow: HWnd;
35087 begin
35088 Result := 0;
35089 if fParent = nil then Exit;
35090 Result := fParent.GetWindowHandle;
35091 end;
35092 {$ENDIF ASM_VERSION}
35094 {$IFDEF ASM_VERSION}
35095 function TControl.GetWindowHandle: HWnd;
35097 MOV ECX, [EAX].fHandle
35098 JECXZ @@1
35099 XCHG EAX, ECX
35101 @@1:
35102 CMP [EAX].fCreateVisible, 0
35103 JNZ @@2
35105 PUSH EAX
35106 XOR EDX, EDX
35107 CALL TControl.Set_Visible
35108 POP EAX
35109 PUSH EAX
35110 //CALL TControl.CreateWindow
35111 CALL CallTControlCreateWindow
35112 { This is a call to Pascal piece of code, which
35113 calls virtual method TControl.CreateWindow }
35114 POP EAX
35116 INC [EAX].fCreateHidden
35117 JMP @@0
35119 @@2: PUSH EAX
35120 //CALL TControl.CreateWindow
35121 CALL CallTControlCreateWindow
35122 POP EAX
35123 @@0:
35124 MOV EAX, [EAX].fHandle
35125 end;
35126 {$ELSE ASM_VERSION} //Pascal
35127 function TControl.GetWindowHandle: HWnd;
35128 begin
35129 if fHandle = 0 then
35130 begin
35131 if not fCreateVisible then
35132 begin
35133 Set_Visible( False );
35134 CreateWindow; //virtual!!!
35135 fCreateHidden := True;
35137 else
35138 CreateWindow; //virtual!!!
35139 end;
35140 Result := fHandle;
35141 end;
35142 {$ENDIF ASM_VERSION}
35145 {$IFDEF _D7orHigher}
35146 // may be it was a good idea to replace CreateWindowEx,
35147 // but Inprise forget about stdcall... In result, asm-version became broken.
35148 //[API CreateWindowEx]
35149 function CreateWindowEx(dwExStyle: DWORD; lpClassName: PChar;
35150 lpWindowName: PChar; dwStyle: DWORD; X, Y, nWidth, nHeight: Integer;
35151 hWndParent: HWND; hMenu: HMENU; hInstance: HINST; lpParam: Pointer): HWND;
35152 stdcall; external user32 name 'CreateWindowExA';
35153 {$ENDIF}
35156 {$IFDEF ASM_VERSION}
35157 //[function TControl.CreateWindow]
35158 function TControl.CreateWindow: Boolean;
35159 const
35160 CS_OFF = CS_OWNDC or CS_CLASSDC or CS_PARENTDC or CS_GLOBALCLASS;
35161 CS_ON = 0; //CS_VREDRAW or CS_HREDRAW;
35162 szWndClass = sizeof( TWndClass );
35163 int_IDC_ARROW = integer( IDC_ARROW );
35165 PUSH EBX
35166 XCHG EBX, EAX
35167 MOV ECX, [EBX].fParent
35168 JECXZ @@chk_handle
35169 XCHG EAX, ECX
35170 CALL GetWindowHandle
35171 TEST EAX, EAX
35172 JZ @@ret_false
35173 @@chk_handle:
35174 MOV ECX, [EBX].fHandle
35175 JECXZ @@prepare_Params
35176 MOV DL, 0
35177 MOV EAX, EBX
35178 CMP [EBX].fCreateHidden, DL
35179 JZ @@create_children
35180 CALL CreateChildWindows
35181 MOV EAX, EBX
35182 MOV DL, 1
35183 CALL Set_Visible
35184 MOV [EBX].fCreateHidden, 0
35185 JMP @@ret_true
35186 @@create_children:
35187 CALL CreateChildWindows
35188 @@ret_true:
35189 MOV AL, 1
35190 POP EBX
35192 @@prepare_params:
35193 PUSH EBP
35194 MOV EBP, ESP
35196 PUSH ECX // Params.WindowClass.lpszClassName := nil
35197 PUSH ECX // Params.WindowClass.lpszMenuName := nil
35198 PUSH ECX // Params.WindowClass.hbrBackground := 0
35199 PUSH int_IDC_ARROW
35200 PUSH ECX
35201 CALL LoadCursor
35202 PUSH EAX // Params.WindowClass.hCursor := LoadCursor( 0, IDC_ARROW )
35203 XOR ECX, ECX
35204 PUSH ECX // Params.WindowClass.hIcon := 0
35205 PUSH [hInstance]// Params.WindowClass.hInstance := hInstance
35206 PUSH ECX // Params.WindowClass.cbWndExtra := 0
35207 PUSH ECX // Params.WindowClass.cbClsExtra := 0
35208 //PUSH offset DefWindowProc // Params.WindowClass.lpfnWndProc := @DefWindowProc
35209 PUSH [EBX].fDefWndProc // Params.WindowClass.lpfnWndProc := fDefWndProc
35210 PUSH [EBX].fClsStyle // Params.WindowClass.style := fStyle
35211 ADD ESP, -64
35212 PUSH ECX
35213 MOV EAX, EBX
35214 MOV EDX, ESP
35215 CALL get_ClassName
35216 POP EDX
35217 MOV EAX, ESP
35218 PUSH EDX
35219 //CALL StrPCopy // StrPCopy( Params.WinClsNamBuf, ClassName )
35220 CALL StrCopy
35221 CALL RemoveStr
35222 PUSH 0 // Params.Param := nil
35223 PUSH [hInstance] // Params.Inst := fInstance
35224 PUSH [EBX].fMenu // Params.Menu := fMenu
35225 MOV DL, 1
35226 MOV EAX, EBX
35227 CALL GetParentWnd
35228 PUSH EAX // Params.WndParent := GetParentWnd( True )
35230 MOV ECX, CW_USEDEFAULT
35231 MOV EAX, [EBX].fBoundsRect.Bottom
35232 MOV EDX, [EBX].fBoundsRect.Top
35233 SUB EAX, EDX
35234 JNZ @@1
35235 MOV EAX, ECX
35236 @@1: PUSH EAX // Params.Height := Height | CW_UseDefault
35237 MOV EAX, [EBX].fBoundsRect.Right
35238 SUB EAX, [EBX].fBoundsRect.Left
35239 {$IFDEF USE_CMOV}
35240 CMOVZ EAX, ECX
35241 {$ELSE}
35242 JNZ @@2
35243 MOV EAX, ECX
35244 @@2: {$ENDIF}
35246 PUSH EAX // Params.Width := Width | CW_UseDefault
35247 MOV EAX, [EBX].fBoundsRect.Left
35248 CMP [EBX].fIsControl, CL
35249 JNZ @@3
35250 TEST byte ptr [EBX].fChangedPosSz, 3
35251 JNZ @@3
35252 MOV EDX, ECX
35253 XCHG EAX, ECX
35254 @@3: PUSH EDX // Params.Y := Top | CW_UseDefault
35255 PUSH EAX // Params.X := Left | CW_UseDefault
35256 PUSH [EBX].fStyle // Params.Style := fStyle
35257 PUSH [EBX].fCaption // Params.Caption := fCaption
35258 LEA EAX, [ESP+40]
35259 PUSH EAX // Params.WinClassName := @Params.WinClsNamBuf
35260 PUSH [EBX].fExStyle // Params.ExStyle := fExStyle
35262 MOV ECX, [EBX].fControlClassName
35263 JECXZ @@registerClass
35264 LEA EAX, [ESP].TCreateWndParams.WindowClass
35265 PUSH EAX // @Params.WindowClass
35266 PUSH ECX // fControlClassName
35267 PUSH [hInstance] // hInstance
35268 CALL GetClassInfo
35269 MOV EAX, [ESP].TCreateWndParams.Inst
35270 MOV [ESP].TCreateWndParams.WindowClass.hInstance, EAX
35271 AND [ESP].TCreateWndParams.WindowClass.style, not CS_OFF
35272 @@registerClass:
35273 CMP [EBX].fDefWndProc, 0
35274 JNE @@fDefWndProc_ready
35275 MOV EAX, [ESP].TCreateWndParams.WindowClass.lpfnWndProc
35276 MOV [EBX].fDefWndProc, EAX
35277 @@fDefWndProc_ready:
35278 MOV ECX, [ESP].TCreateWndParams.WndParent
35279 INC ECX
35280 LOOP @@registerClass1
35281 TEST byte ptr [ESP].TCreateWndParams.Style+3, $40
35282 XCHG EAX, ECX
35283 JNZ @@fin
35284 @@registerClass1:
35285 MOV EAX, [ESP].TCreateWndParams.WinClassName
35286 MOV EDX, [ESP].TCreateWndParams.WindowClass.hInstance
35287 ADD ESP, -szWndClass
35288 PUSH ESP
35289 PUSH EAX
35290 PUSH EDX
35291 CALL GetClassInfo
35292 ADD ESP, szWndClass
35293 TEST EAX, EAX
35294 JNZ @@registered
35295 MOV EAX, [ESP].TCreateWndParams.WinClassName
35296 MOV [ESP].TCreateWndParams.WindowClass.lpszClassName, EAX
35297 MOV [ESP].TCreateWndParams.WindowClass.lpfnWndProc, offset WndFunc
35298 LEA EAX, [ESP].TCreateWndParams.WindowClass
35299 PUSH EAX
35300 CALL RegisterClass
35301 TEST EAX, EAX
35302 JZ @@fin
35303 @@registered:
35304 MOV [CreatingWindow], EBX
35305 CALL CreateWindowEx
35306 MOV [EBX].fHandle, EAX
35307 TEST EAX, EAX
35308 JZ @@fin
35309 PUSH EAX
35310 PUSH offset ID_SELF
35311 PUSH EAX
35313 //SendMessage(fHandle,WM_UPDATEUISTATE,UIS_CLEAR or (UISF_HIDEFOCUS shl 16),0);
35314 PUSH 0
35315 PUSH $10002 //UIS_CLEAR or (UISF_HIDEFOCUS shl 16)
35316 PUSH $0128 //WM_UPDATEUISTATE
35317 PUSH EAX
35318 CALL SendMessage
35320 CALL GetProp
35321 XCHG ECX, EAX
35322 POP EAX
35323 INC ECX
35324 LOOP @@propSet
35325 MOV [CreatingWindow], ECX
35326 PUSH EBX
35327 PUSH offset ID_SELF
35328 PUSH EAX
35329 CALL SetProp
35330 @@propSet:
35331 CMP [EBX].fIsControl, 0
35332 JNZ @@iconSet
35333 MOV EAX, EBX
35334 CALL GetIcon
35335 PUSH EAX
35336 PUSH 1
35337 PUSH WM_SETICON
35338 PUSH EBX
35339 CALL Perform
35340 @@iconSet:
35341 MOV ECX, [EBX].fCreateWndExt
35342 JECXZ @@dblbufcreate
35343 MOV EAX, EBX
35344 CALL ECX
35345 @@dblbufcreate:
35346 MOV EAX, EBX
35347 CALL Dword Ptr [ Global_DblBufCreateWnd ]
35348 @@applyfont:
35349 MOV EAX, EBX
35350 CALL ApplyFont2Wnd
35351 MOV EAX, EBX
35352 CALL ApplyFont2Wnd
35353 XCHG EAX, EBX
35354 CALL CreateChildWindows
35355 MOV AL, 1
35356 @@fin:
35357 MOV ESP, EBP
35358 POP EBP
35359 @@ret_false:
35360 POP EBX
35361 end;
35362 {$ELSE ASM_VERSION} //Pascal
35363 function TControl.CreateWindow: Boolean;
35364 const
35365 CS_OFF = CS_OWNDC or CS_CLASSDC or CS_PARENTDC or CS_GLOBALCLASS;
35366 CS_ON = 0; //CS_VREDRAW or CS_HREDRAW;
35367 var TempClass: TWndClass;
35368 Params: TCreateWndParams;
35369 ClassRegistered: Boolean;
35370 {$IFDEF _FPC}
35371 SClassName: String;
35372 {$ENDIF ASM_VERSION}
35373 begin
35374 {$IFDEF DEBUG_CREATEWINDOW}
35375 LogFileOutput( GetStartDir + 'Session.log', 'TControl.CreateWindow, ' +
35376 ' Self = ' + Int2Str( Integer( @ Self ) ) +
35377 ' Caption = ' + fCaption +
35378 ' fChildren = ' + Int2Hex( Integer( fChildren ), 4 ) +
35379 ' ChildCount = ' + Int2Str( ChildCount ) );
35380 {$ENDIF DEBUG_CREATEWINDOW}
35381 Result := False;
35382 if fParent <> nil then
35383 if fParent.GetWindowHandle = 0 then
35384 Exit;
35385 if fHandle <> 0 then
35386 begin
35387 if fCreateHidden then
35388 begin
35389 CreateChildWindows;
35390 Set_Visible( True );
35391 fCreateHidden := False;
35393 else
35394 begin
35395 CreateChildWindows;
35396 end;
35397 Result := True;
35398 Exit;
35399 end;
35401 FillChar( Params, Sizeof( Params ), 0 );
35402 Params.Caption := PChar( FCaption );
35403 Params.Style := FStyle;
35404 if not fEnabled then
35405 Params.Style := Params.Style or WS_DISABLED;
35406 Params.ExStyle := FExStyle;
35407 Params.WindowClass.style := FClsStyle;
35408 {Params.WindowClass.lpfnWndProc := @ DefWindowProc;
35409 if fDefWndProc <> nil then} //+-+
35410 Params.WindowClass.lpfnWndProc := FDefWndProc;
35411 Params.WindowClass.hCursor := LoadCursor( 0, IDC_ARROW );
35412 Params.WindowClass.hInstance := hInstance;
35413 Params.Inst := hInstance;
35414 {$IFDEF _FPC}
35415 SClassName := SubClassName;
35416 StrCopy( Params.WinClsNamBuf, @ SClassName[ 1 ] );
35417 {$ELSE}
35418 StrCopy( Params.WinClsNamBuf, @ SubClassName[ 1 ] );
35419 {$ENDIF}
35420 Params.WinClassName := @Params.WinClsNamBuf[ 0 ];
35421 Params.WndParent := GetParentWnd( True );
35422 Params.Menu := fMenu;
35423 Params.X := fBoundsRect.Left;
35424 Params.Y := fBoundsRect.Top;
35425 Params.Width := fBoundsRect.Right - fBoundsRect.Left;
35426 if Params.Width = 0 then
35427 Params.Width := CW_UseDefault;
35428 Params.Height := fBoundsRect.Bottom - fBoundsRect.Top;
35429 if Params.Height = 0 then
35430 Params.Height := CW_UseDefault;
35431 if not fIsControl then
35432 begin
35433 if not LongBool( fChangedPosSz and 3 ) then
35434 begin
35435 Params.X := CW_UseDefault;
35436 Params.Y := CW_UseDefault;
35437 end;
35438 end;
35440 if fControlClassName <> nil then
35441 begin // SUBCLASSING WINDOW
35442 GetClassInfo( Params.WindowClass.hInstance, fControlClassName,
35443 Params.WindowClass);
35444 Params.WindowClass.hInstance := Params.Inst;
35445 Params.WindowClass.style := Params.WindowClass.style
35446 and not CS_OFF or CS_ON;
35447 end;
35449 if FDefWndProc = nil then //+
35450 {$IFDEF F_P}
35451 Move( Params.WindowClass.lpfnWndProc, FDefWndProc, Sizeof( Pointer ) );
35452 {$ELSE}
35453 FDefWndProc := Params.WindowClass.lpfnWndProc;
35454 {$ENDIF}
35455 if (Params.WndParent = 0) and (Params.Style and WS_CHILD <> 0) then Exit;
35456 ClassRegistered := GetClassInfo( Params.WindowClass.hInstance,
35457 Params.WinClassName, TempClass );
35458 if not ClassRegistered then
35459 begin
35460 Params.WindowClass.lpszClassName := Params.WinClassName;
35461 Params.WindowClass.lpfnWndProc := fWndFunc;
35462 if RegisterClass( Params.WindowClass ) = 0 then Exit;
35463 end;
35464 {$IFDEF DEBUG_CREATEWINDOW}
35465 LogFileOutput( GetStartDir + 'Session.log',
35466 ' ExStyle=' + Int2Hex( Params.ExStyle, 4 ) +
35467 ' WinClassName=' + Params.WinClassName +
35468 ' Caption=' + Params.Caption +
35469 ' Style=' + Int2Hex( Params.Style, 4 ) +
35470 ' X=' + Int2Str( Params.X ) +
35471 ' Y=' + Int2Str( Params.Y ) +
35472 ' Width=' + Int2Str( Params.Width ) +
35473 ' Height=' + Int2Str( Params.Height ) +
35474 ' WndParent=' + Int2Str( Params.WndParent ) +
35475 ' Menu=' + Int2Str( Params.Menu ) +
35476 ' hInstance=' + Int2Str( Params.WindowClass.hInstance ) +
35477 ' Param=' + Int2Str( Integer( Params.Param ) )
35479 {$ENDIF}
35480 CreatingWindow := @Self;
35481 fHandle := CreateWindowEx( Params.ExStyle, Params.WinClassName,
35482 Params.Caption, Params.Style, Params.X, Params.Y,
35483 Params.Width, Params.Height, Params.WndParent,
35484 Params.Menu, Params.WindowClass.hInstance,
35485 Params.Param );
35486 if fHandle = 0 then Exit;
35487 SendMessage( fHandle, $0128 {WM_UPDATEUISTATE},
35488 2 {UIS_CLEAR} or (1 {UISF_HIDEFOCUS} shl 16),0);
35489 if GetProp(FHandle,ID_SELF) = 0 then
35490 begin
35491 CreatingWindow := nil;
35492 SetProp(FHandle, ID_SELF, THandle(@Self));
35493 end;
35494 //***
35495 if not fIsControl then
35496 SendMessage( fHandle, WM_SETICON, 1 {ICON_BIG}, GetIcon );
35497 if Assigned( FCreateWndExt ) then
35498 FCreateWndExt( @Self );
35499 Global_DblBufCreateWnd( @ Self );
35500 ApplyFont2Wnd;
35501 ApplyFont2Wnd;
35503 CreateChildWindows;
35504 Result := True;
35505 end;
35506 {$ENDIF}
35509 //[procedure TControl.CreateSubclass]
35510 procedure TControl.CreateSubclass(var Params: TCreateParams;
35511 ControlClassName: PChar);
35512 const
35513 CS_OFF = CS_OWNDC or CS_CLASSDC or CS_PARENTDC or CS_GLOBALCLASS;
35514 CS_ON = 0; //CS_VREDRAW or CS_HREDRAW;
35516 SaveInstance: THandle;
35517 begin
35518 if fControlClassName <> nil then
35519 with Params do
35520 begin
35521 SaveInstance := WindowClass.hInstance;
35522 if not GetClassInfo(HInstance, fControlClassName, WindowClass) and
35523 not GetClassInfo(0, fControlClassName, WindowClass)
35524 //and not GetClassInfo(HInstance {MainInstance}, fControlClassName, WindowClass)
35525 then
35526 GetClassInfo(WindowClass.hInstance, fControlClassName, WindowClass);
35527 WindowClass.hInstance := SaveInstance;
35528 WindowClass.style := WindowClass.style and not CS_OFF or CS_ON;
35529 end;
35530 end;
35532 //[FUNCTION WndProcMous]
35533 {$IFDEF ASM_VERSION}
35534 function WndProcMouse(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
35536 PUSH EBX
35537 PUSH ESI
35538 XCHG EBX, EAX
35540 XOR ECX, ECX // Rslt not used. ECX <= Result = 0
35541 MOV EAX, [EDX].TMsg.message
35542 SUB AH, WM_MOUSEFIRST shr 8
35543 CMP EAX, $20A - WM_MOUSEFIRST //WM_MOUSELAST - WM_MOUSEFIRST
35544 JA @@exit
35546 PUSH dword ptr [EDX].TMsg.lParam // prepare X, Y
35548 PUSHAD
35550 PUSH VK_MENU
35551 CALL GetKeyState
35552 ADD EAX, EAX
35553 POPAD
35554 XCHG EAX, EDX
35555 MOV EAX, [EAX].TMsg.wParam
35557 JNC @@noset_MKALT
35558 {$IFDEF PARANOIA}
35559 DB $0C, MK_ALT
35560 {$ELSE}
35561 OR AL, MK_ALT
35562 {$ENDIF}
35563 @@noset_MKALT:
35565 PUSH EAX // prepare Shift
35567 LEA ESI, [EBX].TControl.fOnMouseDown
35568 CALL dword ptr [EDX*4 + @@jump_table]
35570 @@call_evnt:
35571 PUSH ECX // prepare Button, StopHandling
35572 MOV ECX, ESP // ECX = @MouseData
35574 CMP word ptr [ESI].TMethod.Code+2, 0
35575 JZ @@after_call
35577 MOV EDX, EBX // EDX = Self_
35578 MOV EAX, [ESI].TMethod.Data // EAX = Target_
35579 CALL dword ptr [ESI].TMethod.Code
35581 @@after_call:
35582 POP ECX
35583 POP EDX
35584 POP EDX
35585 MOV CL, CH // Result := StopHandling
35587 @@exit:
35588 XCHG EAX, ECX
35589 POP ESI
35590 POP EBX
35593 @@jump_table:
35594 DD Offset[@@MMove],Offset[@@LDown],Offset[@@LUp],Offset[@@LDblClk]
35595 DD Offset[@@RDown],Offset[@@RUp],Offset[@@RDblClk]
35596 DD Offset[@@MDown],Offset[@@MUp],Offset[@@MDblClk],Offset[@@MWheel]
35598 @@MDown: INC ECX
35599 @@RDown: INC ECX
35600 @@LDown: INC ECX
35601 //LEA ESI, [EBX].TControl.fOnMouseDown
35604 @@MUp: INC ECX
35605 @@RUp: INC ECX
35606 @@LUp: INC ECX
35607 //LEA ESI, [EBX].TControl.fOnMouseUp
35608 LODSD
35609 LODSD
35612 @@MMove: LEA ESI, [EBX].TControl.fOnMouseMove
35613 //ADD ESI, 16
35616 @@MDblClk: INC ECX
35617 @@RDblClk: INC ECX
35618 @@LDblClk: INC ECX
35619 LEA ESI, [EBX].TControl.fOnMouseDblClk
35620 //ADD ESI, 24
35623 @@MWheel:LEA ESI, [EBX].TControl.fOnMouseWheel
35624 //ADD ESI, 32
35625 //RET
35626 end;
35627 {$ELSE ASM_VERSION} //Pascal
35628 function WndProcMouse(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
35629 var MouseData: TMouseEventData;
35630 begin
35631 Result := False;
35632 if (Msg.message >= WM_MOUSEFIRST) and (Msg.message <= $20A {WM_MOUSELAST}) and
35633 (Msg.hwnd = Self_.fHandle) then
35634 with MouseData do
35635 begin
35636 Shift := Msg.wParam;
35637 if GetKeyState( VK_MENU ) < 0 then
35638 Shift := Shift or MK_ALT;
35639 X := LoWord( Msg.lParam );
35640 Y := HiWord( Msg.lParam );
35641 Button := mbNone;
35642 StopHandling := FALSE;
35643 Rslt := 0; // needed ?
35644 case Msg.message of
35645 WM_LBUTTONDOWN:
35646 if Assigned( Self_.OnMouseDown ) then
35647 begin
35648 Button := mbLeft;
35649 Self_.OnMouseDown( Self_, MouseData );
35650 end;
35651 WM_RBUTTONDOWN:
35652 if Assigned( Self_.OnMouseDown ) then
35653 begin
35654 Button := mbRight;
35655 Self_.OnMouseDown( Self_, MouseData );
35656 end;
35657 WM_MBUTTONDOWN:
35658 if Assigned( Self_.OnMouseDown ) then
35659 begin
35660 Button := mbMiddle;
35661 Self_.OnMouseDown( Self_, MouseData );
35662 end;
35663 WM_LBUTTONUP:
35664 if Assigned( Self_.OnMouseUp ) then
35665 begin
35666 Button := mbLeft;
35667 Self_.OnMouseUp( Self_, MouseData );
35668 end;
35669 WM_RBUTTONUP:
35670 if Assigned( Self_.OnMouseUp ) then
35671 begin
35672 Button := mbRight;
35673 Self_.OnMouseUp( Self_, MouseData );
35674 end;
35675 WM_MBUTTONUP:
35676 if Assigned( Self_.OnMouseUp ) then
35677 begin
35678 Button := mbMiddle;
35679 Self_.OnMouseUp( Self_, MouseData );
35680 end;
35681 WM_MOUSEMOVE:
35682 if Assigned( Self_.OnMouseMove ) then
35683 Self_.OnMouseMove( Self_, MouseData );
35684 WM_LBUTTONDBLCLK:
35685 if Assigned( Self_.OnMouseDblClk ) then
35686 begin
35687 Button := mbLeft;
35688 Self_.OnMouseDblClk( Self_, MouseData );
35689 end;
35690 WM_RBUTTONDBLCLK:
35691 if Assigned( Self_.OnMouseDblClk ) then
35692 begin
35693 Button := mbRight;
35694 Self_.OnMouseDblClk( Self_, MouseData );
35695 end;
35696 WM_MBUTTONDBLCLK:
35697 if Assigned( Self_.OnMouseDblClk ) then
35698 begin
35699 Button := mbMiddle;
35700 Self_.OnMouseDblClk( Self_, MouseData );
35701 end;
35702 $020A {WM_MOUSEWHEEL}:
35703 if Assigned( Self_.OnMouseWheel ) then
35704 Self_.OnMouseWheel( Self_, MouseData );
35705 else
35706 Exit; //Result := False;
35707 end;
35708 Result := StopHandling;
35709 end;
35710 end;
35711 {$ENDIF ASM_VERSION}
35712 //[END WndProcMous]
35714 //[FUNCTION WndProcKeybd]
35715 {$IFDEF ASM_VERSION}
35716 function WndProcKeybd( Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
35718 PUSH EBX
35719 MOV ECX, [EDX].TMsg.message
35720 SUB CX, $100
35721 CMP ECX, 5
35722 JA @@fin_false
35723 XCHG EBX, EAX // EBX = @Self
35724 XCHG EAX, ECX // EAX = message - WM_KEYFIRST
35725 LEA ECX, [EBX].TControl.fOnKeyUp
35726 JZ @@event
35727 {$IFDEF PARANOIA}
35728 DB $34, 1
35729 {$ELSE}
35730 XOR AL, 1
35731 {$ENDIF}
35732 JZ @@event
35733 LEA ECX, [EBX].TControl.fOnKeyDown
35734 {$IFDEF PARANOIA}
35735 DB $34, 1
35736 {$ELSE}
35737 XOR AL, 1
35738 {$ENDIF}
35739 JZ @@event
35740 {$IFDEF PARANOIA}
35741 DB $34, 4
35742 {$ELSE}
35743 XOR AL, 4
35744 {$ENDIF}
35745 JZ @@event
35746 LEA ECX, [EBX].TControl.fOnChar
35747 {$IFDEF PARANOIA}
35748 DB $34, 6
35749 {$ELSE}
35750 XOR AL, 2 xor 4
35751 {$ENDIF}
35752 JZ @@event
35753 {$IFDEF PARANOIA}
35754 DB $34, 4
35755 {$ELSE}
35756 XOR AL, 6 xor 2
35757 {$ENDIF}
35758 JNZ @@fin_false
35759 @@event:
35760 CMP word ptr [ECX].TMethod.Code+2, 0
35761 JZ @@fin_false
35762 PUSH EDX
35763 PUSH ECX
35764 LEA ECX, [EDX].TMsg.wParam
35765 PUSH ECX
35766 CALL GetShiftState
35767 POP ECX // @wParam
35768 XCHG EAX, [ESP] // ShiftState; EAX=@event
35769 MOV EDX, EBX // @Self
35770 MOV EBX, [EAX].TMethod.Code
35771 MOV EAX, [EAX].TMethod.Data
35772 CALL EBX
35774 POP EDX
35775 MOV ECX, [EDX].TMsg.wParam
35776 JECXZ @@fin_true
35778 @@fin_false:
35779 XOR EAX, EAX
35780 POP EBX
35783 @@fin_true:
35784 MOV AL, 1
35785 POP EBX
35786 end;
35787 {$ELSE ASM_VERSION} //Pascal
35788 function WndProcKeybd(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
35789 var C : Char;
35790 begin
35791 Result := True;
35792 case Msg.message of
35793 WM_KEYDOWN, WM_SYSKEYDOWN:
35794 if assigned( Self_.fOnKeyDown ) then
35795 Self_.fOnKeyDown( Self_, Msg.wParam, GetShiftState );
35796 WM_KEYUP, WM_SYSKEYUP:
35797 if assigned( Self_.fOnKeyUp ) then
35798 Self_.fOnKeyUp( Self_, Msg.wParam, GetShiftState );
35799 WM_CHAR, WM_SYSCHAR:
35800 if assigned( Self_.fOnChar ) then
35801 begin
35802 C := Char( Msg.wParam );
35803 Self_.fOnChar( Self_, C, GetShiftState );
35804 Msg.wParam := Integer( C );
35805 end;
35806 else begin
35807 Result := False;
35808 Exit;
35809 end;
35810 end;
35811 if Msg.wParam <> 0 then
35812 Result := False;
35813 end;
35814 {$ENDIF ASM_VERSION}
35815 //[END WndProcKeybd]
35817 //[function WndProcDummy]
35818 function WndProcDummy(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
35819 begin
35820 Result := False;
35821 end;
35823 //[procedure ExcludeCtlsWhichCannotDblBuf]
35824 procedure ExcludeCtlsWhichCannotDblBuf( Sender, ParentCtl: PControl; DC: HDC );
35825 var I: Integer;
35826 C: PControl;
35827 R, R1: TRect;
35828 begin
35829 for I := 0 to ParentCtl.fChildren.Count-1 do
35830 begin
35831 C := ParentCtl.fChildren.Items[ I ];
35832 if C.fCannotDoubleBuf then
35833 begin
35834 GetWindowRect( Sender.fHandle, R );
35835 GetWindowRect( C.fHandle, R1 );
35836 OffsetRect( R1, -R.Left, -R.Top );
35837 ExcludeClipRect(DC, R1.Left, R1.Top, R1.Right, R1.Bottom);
35839 else
35840 ExcludeCtlsWhichCannotDblBuf( Sender, C, DC );
35841 end;
35842 end;
35844 //[procedure DoReleaseDblBufBmp]
35845 procedure DoReleaseDblBufBmp( Sender: PControl );
35846 begin
35847 if Sender.fDblBufBmp <> 0 then
35848 DeleteObject( Sender.fDblBufBmp );
35849 end;
35851 //[procedure DoDrawChildrenDblBuffered]
35852 procedure DoDrawChildrenDblBuffered( DC: HDC; WndParent: HWnd; const RectParent: TRect;
35853 W: HWnd );
35854 var R, CR: TRect;
35855 Save: Integer;
35856 P, P0: TPoint;
35857 begin
35858 while W <> 0 do
35859 begin
35860 if IsWindowVisible( W ) then
35861 begin
35862 Save := SaveDC( DC );
35863 GetWindowRect( W, R );
35864 GetWindowOrgEx( DC, P );
35865 SetWindowOrgEx( DC, P.x - ( R.Left - RectParent.Left ), P.y - ( R.Top - RectParent.Top ), nil );
35866 IntersectClipRect( DC, 0, 0, R.Right - R.Left, R.Bottom - R.Top );
35867 SendMessage( W, WM_PRINT, DC, PRF_NONCLIENT );
35868 GetClientRect( W, CR );
35869 P0.x := 0; P0.y := 0;
35870 ClientToScreen( W, P0 );
35871 OffsetRect( CR, P0.x, P0.y );
35872 SetWindowOrgEx( DC, P.x - (CR.Left - RectParent.Left), P.y - (CR.Top - RectParent.Top), nil );
35873 IntersectClipRect( DC, 0, 0, CR.Right - CR.Left, CR.Bottom - CR.Top );
35874 SendMessage( W, WM_ERASEBKGND, DC, 0 );
35875 SendMessage( W, WM_PAINT, DC, 0 );
35876 DoDrawChildrenDblBuffered( DC, W, CR, GetWindow( W, GW_CHILD ) );
35877 RestoreDC( DC, Save );
35878 end;
35879 W := GetWindow( W, GW_HWNDNEXT );
35880 end;
35881 end;
35883 //[procedure DoDrawDblBuffered]
35884 procedure DoDrawDblBuffered( Sender: PControl );
35885 var R: TRect;
35886 DC0, DC1, DC2: HDC;
35887 OldBmp: HBitmap;
35888 R2: TRect;
35889 P1, P2: TPoint;
35890 ClientOnly: Boolean;
35891 OldPaintDC: HDC;
35892 {$IFDEF DEBUGDBLBUFF}
35893 Tmp: PBitmap;
35894 {$ENDIF}
35895 begin
35896 if not GetUpdateRect( Sender.fHandle, R, FALSE ) then
35897 Exit; // nothing to paint
35899 Sender.fDblBufPainting := TRUE;
35901 ClientOnly := Sender.fIsForm {and (WinVer < wvNT)};
35902 if ClientOnly then
35903 GetClientRect( Sender.fHandle, R )
35904 else
35905 begin
35906 GetWindowRect( Sender.fHandle, R );
35907 OffsetRect( R, -R.Left, -R.Top );
35908 end;
35910 DC0 := GetDC( Sender.fHandle );
35911 DC1 := CreateCompatibleDC( DC0 );
35912 if Sender.fDblBufBmp = 0 then
35913 Sender.Add2AutoFreeEx( TObjectMethod( MakeMethod( Sender, @ DoReleaseDblBufBmp ) ) );
35914 if (Sender.fDblBufW < R.Right) or (Sender.fDblBufH < R.Bottom) or
35915 (Sender.fDblBufW > R.Right + 32) or (Sender.fDblBufH > R.Bottom + 32) then
35916 if Sender.fDblBufBmp <> 0 then
35917 begin
35918 DeleteObject( Sender.fDblBufBmp );
35919 Sender.fDblBufBmp := 0;
35920 end;
35921 if Sender.fDblBufBmp = 0 then
35922 begin
35923 Sender.fDblBufBmp := CreateCompatibleBitmap( DC0, R.Right, R.Bottom );
35924 Sender.fDblBufW := R.Right;
35925 Sender.fDblBufH := R.Bottom;
35926 end;
35927 OldBmp := SelectObject( DC1, Sender.fDblBufBmp );
35929 OldPaintDC := Sender.fPaintDC;
35930 Sender.fPaintDC := DC1;
35931 if ClientOnly then
35932 begin
35933 GetClientRect( Sender.fHandle, R2 );
35934 P2.x := 0; P2.y := 0;
35935 ClientToScreen( Sender.fHandle, P2 );
35936 OffsetRect( R2, P2.x, P2.y );
35937 SendMessage( Sender.fHandle, WM_ERASEBKGND, DC1, 0 );
35938 SendMessage( Sender.fHandle, WM_PAINT, DC1, 0 );
35939 DoDrawChildrenDblBuffered( DC1, Sender.fHandle, R2,
35940 GetWindow( Sender.fHandle, GW_CHILD ) );
35942 else
35943 begin
35944 {Sender.Perform( WM_PRINT, DC1,
35945 PRF_CLIENT or PRF_NONCLIENT or PRF_ERASEBKGND or PRF_CHILDREN );}
35946 GetWindowRect( Sender.fHandle, R2 );
35947 DoDrawChildrenDblBuffered( DC1, Sender.fHandle, R2, Sender.fHandle );
35948 end;
35949 //Sender.fPaintDC := DC1;
35951 DC2 := GetWindowDC( Sender.fHandle );
35953 ExcludeCtlsWhichCannotDblBuf( Sender, Sender, DC2 );
35955 P1.x := 0; P1.y := 0;
35956 if ClientOnly then
35957 begin
35958 GetWindowRect( Sender.fHandle, R2 );
35959 ClientToScreen( Sender.fHandle, P1 );
35960 P1.x := P1.x - R2.Left;
35961 P1.y := P1.y - R2.Top;
35962 GetClientRect( Sender.fHandle, R );
35963 end;
35964 BitBlt( DC2, P1.x, P1.y, R.Right, R.Bottom, DC1, 0, 0, SRCCOPY );
35966 {$IFDEF DEBUGDBLBUFF}
35967 Tmp := NewDIBBitmap( R.Right, R.Bottom, pf16bit );
35968 BitBlt( Tmp.Canvas.Handle, 0, 0, R.Right, R.Bottom, DC1, 0, 0, SRCCopy );
35969 Tmp.SaveToFile( 'c:\tmp.bmp' );
35970 Tmp.Free;
35971 {$ENDIF}
35973 ReleaseDC( Sender.fHandle, DC2 );
35975 SelectObject( DC1, OldBmp );
35976 DeleteDC( DC1 );
35977 ReleaseDC( Sender.fHandle, DC0 );
35979 Sender.fPaintDC := OldPaintDC;
35980 ValidateRect( Sender.fHandle, nil );
35982 Sender.fDblBufPainting := FALSE;
35983 end;
35985 //[function WndProcBufferedDraw]
35986 function WndProcBufferedDraw( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
35987 var Self_DblBufTopParent: PControl;
35988 begin
35989 Result := False;
35990 //if AppletTerminated then Exit;
35991 case Msg.message of
35992 WM_ERASEBKGND:
35993 begin
35994 if Self_.fCannotDoubleBuf then Exit;
35995 if Self_.DblBufTopParent <> nil then
35996 // if the Control is not DoubleBuffered, and none of its Parent controls are
35997 // DoubleBuffered, than ignore this call in Global_OnBufferedDraw, and work
35998 // as usual.
35999 begin // Call made in WndProcBufferedDraw of the top DoubleBuffered
36000 // Parent control, while processing WM_PAINT
36001 if Self_.fTransparent
36002 // Handle opaque control as usual.
36003 // For transparent (child) controls, do nothing at all
36004 // in responce to WM_ERASEBKGND (just tell to the system, that
36005 // the operation completed).
36007 // If DoubleBuffered control or control's DoubleBuffered parent
36008 // is not painting now through buffer, just ignore the message
36009 not Self_.DblBufTopParent.fDblBufPainting
36010 then
36011 begin
36012 if Self_.fParent <> nil then
36013 begin
36014 Rslt := 1;
36015 Result := TRUE;
36016 Exit;
36017 end;
36018 end;
36019 end;
36020 end;
36021 WM_PAINT:
36022 begin
36023 if Self_.fCannotDoubleBuf then Exit;
36024 Self_DblBufTopParent := Self_.DblBufTopParent;
36025 if Self_DblBufTopParent = nil then
36026 // if the Control is not DoubleBuffered, and none of its Parent controls are
36027 // DoubleBuffered, than ignore this call in Global_OnBufferedDraw, and work
36028 // as usual.
36029 Exit;
36030 if Self_DblBufTopParent <> Self_ then
36031 // if one of the Parent controls is DoubleBuffered, than ignore this call
36032 // in Global_OnBufferedDraw, and work as usual (actually this allows to
36033 // paint children of the DoubleBuffered Parent control to be painted on
36034 // its buffer).
36035 begin
36036 if (not Self_DblBufTopParent.fDblBufPainting) or
36037 (Self_DblBufTopParent.fPaintDC = 0) then
36038 begin // Usual call. Ignore it.
36039 ValidateRect( Self_.fHandle, nil );
36040 //RedrawWindow( Self_.fHandle, nil, 0, RDW_VALIDATE ); experiment
36041 if not Self_DblBufTopParent.fDblBufPainting then
36042 begin
36043 Self_.DblBufTopParent.Invalidate;
36044 //RedrawWindow( Self_DblBufTopParent.fHandle, nil, 0, RDW_INVALIDATE ); exp.
36045 //RedrawWindow( Self_DblBufTopParent.fHandle, nil, 0, RDW_UPDATENOW ); exp.
36046 end;
36047 Rslt := 0;
36048 Result := True;
36049 end;
36050 Exit; // Call from DoDrawDblBuffered of the top doublebuffered Parent
36051 end;
36052 if Msg.wParam <> 0 then Exit;
36053 DoDrawDblBuffered( Self_ );
36054 Rslt := 0;
36055 Result := True;
36056 end;
36057 WM_NCPAINT:
36058 begin
36059 if Self_.fIsForm {and (WinVer < wvNT)} then Exit;
36060 if Self_.CannotDoubleBuf then Exit;
36061 Self_DblBufTopParent := Self_.DblBufTopParent;
36062 if Self_DblBufTopParent = nil then
36063 // if the Control is not DoubleBuffered, and none of its Parent controls are
36064 // DoubleBuffered, than ignore this call in Global_OnBufferedDraw, and work
36065 // as usual.
36066 Exit;
36067 //if Self_.DblBufTopParent <> Self_ then
36068 // if one of the Parent controls is DoubleBuffered, than ignore this call
36069 // in Global_OnBufferedDraw, and work as usual (actually this allows to
36070 // paint children of the DoubleBuffered Parent control to be painted on
36071 // its buffer).
36072 begin
36073 if not Self_DblBufTopParent.fDblBufPainting
36074 then
36075 begin // Usual call. Ignore it.
36076 //ValidateRect( Self_.fHandle, nil );
36077 Rslt := 0;
36078 Result := True;
36079 end;
36080 end;
36081 end;
36082 WM_SETTEXT:
36083 begin
36084 if Self_.DblBufTopParent = nil then Exit;
36085 if not Self_.fIsStaticControl then Exit;
36086 ShowWindow( Self_.fHandle, SW_HIDE );
36087 Rslt := DefWindowProc( Self_.fHandle, WM_SETTEXT, Msg.wParam, Msg.lParam );
36088 ShowWindow( Self_.fHandle, SW_SHOWNA );
36089 UpdateWindow( Self_.fHandle ); // necessary!!!
36090 Result := True;
36091 end;
36092 WM_HSCROLL, WM_VSCROLL, WM_WINDOWPOSCHANGED:
36093 begin
36094 if Self_.DblBufTopParent = nil then Exit;
36095 Self_.Invalidate;
36096 end;
36097 WM_COMMAND:
36098 case HiWord( Msg.wParam ) of
36099 LBN_SELCHANGE {, CBN_SELCHANGE }:
36100 begin
36101 if Self_.DblBufTopParent = nil then Exit;
36102 Self_.Invalidate;
36103 end;
36104 end;
36105 end;
36106 end;
36108 const
36109 MM_MCINOTIFY = $3B9;
36111 {$IFDEF ASM_VERSION}
36113 {$DEFINE ASM_LOCAL}
36114 {$IFDEF NEW_MODAL}
36115 {$UNDEF ASM_LOCAL}
36116 {$ENDIF}
36118 {$ELSE}
36120 {$IFDEF ASM_LOCAL}
36121 {$UNDEF ASM_LOCAL}
36122 {$ENDIF}
36124 {$ENDIF}
36126 {$IFDEF ASM_LOCAL}
36127 //[function TControl.WndProc]
36128 function TControl.WndProc( var Msg: TMsg ): Integer;
36129 asm //cmd //opd
36130 PUSH EBX
36131 PUSH ESI
36132 PUSH EDI
36133 XCHG ESI, EAX
36134 MOV EDI, EDX
36135 XOR EAX, EAX
36136 CMP EAX, [EDX].TMsg.hWnd
36137 JNE @@1
36138 CMP EAX, [ESI].TControl.fHandle
36139 JNE @@1
36140 MOV EAX, [EDX].TMsg.hWnd
36141 MOV [ESI].TControl.fHandle, EAX
36142 @@1:
36143 PUSH 0
36144 MOV ECX, ESP
36145 MOV EAX, ESI
36146 CALL dword ptr [Global_OnBufferedDraw]
36147 TEST AL, AL
36148 POP EAX
36149 JNZ @@pass2defproc
36151 CMP [AppletRunning], 0
36152 JZ @@dyn2
36153 MOV ECX, [Applet]
36154 JECXZ @@dyn2
36155 CMP ECX, ESI
36156 JE @@dyn2
36158 CALL @@onmess
36160 @@dyn2: MOV ECX, ESI
36161 CALL @@onmess
36163 MOV EBX, [ESI].TControl.fOnDynHandlers
36164 MOV EAX, ESI
36165 CALL @@callonmes
36167 @@flicksproc:
36168 MOV EAX, ESI
36169 MOV EDX, EDI
36170 PUSH 0
36171 MOV ECX, ESP
36172 CALL dword ptr [ESI].TControl.fWndProcResizeFlicks
36173 TEST AL, AL
36174 POP EAX
36175 JNZ @@pass2defproc
36177 MOVZX EAX, word ptr [EDI].TMsg.message
36179 //CMP word ptr [EDI].TMsg.message, WM_CLOSE
36180 CMP AX, WM_CLOSE
36181 //********************************************************** Changed By M.Gerasimov
36182 // JNE @@chk_WM_NCDESTROY
36183 JNE @@chk_WM_DESTROY
36184 //********************************************************** Changed By M.Gerasimov
36186 MOV ECX, [ESI].TControl.fOnClose.TMethod.Code
36187 JECXZ @@wm_close1
36188 MOV EBX, ECX
36189 PUSH 1
36190 MOV ECX, ESP
36191 MOV EDX, ESI
36192 MOV EAX, [ESI].TControl.fOnClose.TMethod.Data
36193 CALL EBX
36194 POP ECX
36195 INC ECX
36196 LOOP @@wm_close0
36197 CMP [AppletRunning], CL
36198 JZ @@wm_close0
36199 //XOR EAX, EAX
36200 //MOV [ESI].TControl.fModalResult, 0
36201 JMP @@0pass2defproc
36203 /////////////////
36204 @@onmess:
36205 MOV EAX, [ECX].TControl.fOnMessage.TMethod.Data
36206 MOV EBX, [ECX].TControl.fOnMessage.TMethod.Code
36207 @@callonmes:
36208 TEST EBX, EBX
36209 JNZ @@onmess1 // @@dynmes1
36210 @@2onmessret:
36212 @@onmess1:
36213 PUSH 0
36215 MOV EDX, EDI
36216 MOV ECX, ESP
36217 CALL EBX
36218 TEST AL, AL
36220 POP EAX
36221 JZ @@2onmessret
36222 POP EDX // pop retaddr
36223 JMP @@pass2defproc
36224 /////////////////
36226 @@wm_close0:
36227 XOR EAX, EAX
36228 MOV [ESI].TControl.fOnClose.TMethod.Code, EAX
36229 @@wm_close1:
36230 MOV EAX, ESI
36231 CALL TControl.IsMainWindow
36232 TEST AL, AL
36233 MOV ECX, [Applet]
36234 JNZ @@wm_close2
36235 CMP ESI, ECX
36236 JNE @@calldef
36238 @@wm_close2:
36239 JECXZ @@postquit
36240 CMP ECX, ESI
36241 JE @@postquit
36242 PUSH 0
36243 PUSH 0
36244 PUSH WM_CLOSE
36245 PUSH ECX
36246 CALL TControl.Perform
36247 @@postquit:
36248 PUSH 0
36249 CALL PostQuitMessage
36250 //XOR EAX, EAX
36251 JMP @@0pass2defproc
36253 //********************************************************** Added By M.Gerasimov
36255 @@chk_WM_DESTROY:
36256 {CMP word ptr [EDI].TMsg.message, WM_DESTROY
36257 JNE @@chk_WM_NCDESTROY
36258 PUSH GW_CHILD
36259 PUSH [ESI].fHandle
36260 CALL GetWindow
36261 TEST EAX,EAX
36262 JZ @@chk_WM_NCDESTROY
36263 @@RmvNext:
36264 PUSH EAX
36265 PUSH offset[ID_PREVPROC]
36266 PUSH EAX
36267 CALL GetProp
36268 TEST EAX,EAX
36269 JZ @@GetNextChild
36270 POP EAX
36271 PUSH EAX
36272 PUSH offset[ID_PREVPROC]
36273 PUSH EAX
36274 CALL RemoveProp
36275 @@GetNextChild:
36276 POP EAX
36277 PUSH GW_HWNDNEXT
36278 PUSH EAX
36279 CALL GetWindow
36280 TEST EAX,EAX
36281 JNZ @@RmvNext}
36283 //********************************************************** Added By M.Gerasimov
36284 @@chk_WM_NCDESTROY:
36285 //CMP word ptr [EDI].TMsg.message, WM_NCDESTROY
36286 CMP AX, WM_NCDESTROY
36287 JNE @@chk_CM_RELEASE
36288 //********************************************************** Added By M.Gerasimov
36290 PUSH offset[ID_SELF]
36291 PUSH [ESI].fHandle
36292 CALL RemoveProp
36294 //********************************************************** Added By M.Gerasimov
36296 MOV ECX, [Applet]
36297 JECXZ @@nc_destroy1
36298 MOV EAX, [ESI].TControl.fHandle
36299 CMP EAX, [ECX].TControl.fHandle
36300 JE @@calldef
36301 @@nc_destroy1:
36302 MOV EAX, ESI
36303 CALL TControl.IsMainWindow
36304 TEST AL, AL
36305 JZ @@nc_destroy2
36306 PUSH 0
36307 PUSH 0
36308 PUSH CM_RELEASE
36309 PUSH [ESI].TControl.fHandle
36310 CALL PostMessage
36311 JMP @@calldef
36313 @@nc_destroy2:
36314 MOV EAX, [ESI].TControl.fParent
36315 CMP EAX, [Applet]
36316 JNE @@calldef
36318 MOV [ESI].TControl.fNCDestroyed, 1
36319 @@do_free:
36320 XCHG EAX, ESI
36321 CALL TObj.Free
36323 XOR EAX, EAX
36324 JMP @@exit // WM_NCDESTROY and CM_RELEASE
36325 // is not a subject to pass it
36326 // to fPass2DefProc
36328 @@chk_CM_RELEASE:
36329 //CMP word ptr [EDI].TMsg.message, CM_RELEASE
36330 CMP AX, CM_RELEASE
36331 JNE @@chk_WM_SIZE
36333 MOV [ESI].TControl.fDestroying, 1
36334 JMP @@do_free
36336 @@chk_WM_SIZE:
36337 //CMP word ptr [EDI].TMsg.message, WM_SIZE
36338 CMP AX, WM_SIZE
36339 JNE @@chk_WM_SHOWWINDOW
36341 MOV EDX, EDI
36342 MOV EAX, ESI
36343 CALL TControl.CallDefWndProc
36344 PUSH EAX
36346 MOV ECX, [EDI].TMsg.wParam
36347 MOV [ESI].TControl.fWindowState, CL
36349 CMP [ESI].TControl.fIsForm, 0
36350 JNZ @@doGlobalAlignSelf
36351 MOV EAX, [ESI].TControl.fParent
36352 TEST EAX, EAX
36353 JZ @@doGlobalAlignSelf
36354 CALL dword ptr [Global_Align]
36355 @@doGlobalAlignSelf:
36356 XCHG EAX, ESI
36357 CALL dword ptr [Global_Align]
36359 //POP EAX
36360 JMP @@popeax_exit
36361 // fPass2DefProc not needed,
36362 // CallDefWndProc already called
36364 @@chk_WM_SHOWWINDOW:
36365 //CMP word ptr [EDI].TMsg.message, WM_SHOWWINDOW
36366 CMP AX, WM_SHOWWINDOW
36367 JNE @@chk_WM_SYSCOMMAND
36369 MOV ECX, [EDI].TMsg.lParam
36370 LOOP @@chk_SW_PARENTOPENING
36372 PUSH [ESI].TControl.fHandle
36373 CALL IsIconic
36374 XOR EBX, EBX
36375 MOV BL, SW_SHOWMINNOACTIVE
36376 TEST EAX, EAX
36377 JNZ @@store_action
36379 PUSH [ESI].TControl.fHandle
36380 CALL IsZoomed
36381 MOV BL, SW_SHOWMAXIMIZED
36382 TEST EAX, EAX
36383 JNZ @@store_action
36385 MOV BL, SW_SHOWNOACTIVATE
36386 @@store_action:
36387 MOV [ESI].TControl.fShowAction, EBX
36388 @@2calldef:
36389 JMP @@calldef
36391 @@chk_SW_PARENTOPENING:
36392 DEC ECX
36393 LOOP @@2calldef
36395 MOV ECX, [ESI].TControl.fShowAction
36396 JECXZ @@ret_0
36398 PUSH ECX
36399 PUSH [ESI].TControl.fHandle
36400 CALL ShowWindow
36402 XOR EAX, EAX
36403 MOV [ESI].TControl.fShowAction, EAX
36404 @@ret_0:
36405 //XOR EAX, EAX
36406 JMP @@0pass2defproc
36408 @@chk_WM_SYSCOMMAND:
36409 //CMP word ptr [EDI].TMsg.message, WM_SYSCOMMAND
36410 CMP AX, WM_SYSCOMMAND
36411 JNE @@chk_WM_SETFOCUS
36413 MOV EAX, [EDI].TMsg.wParam
36414 {$IFDEF PARANOIA}
36415 DB $24, $F0
36416 {$ELSE}
36417 AND AL, $F0
36418 {$ENDIF}
36419 CMP AX, SC_MINIMIZE
36420 JNE @@calldef
36422 MOV EAX, ESI
36423 CALL TControl.IsMainWindow
36424 TEST AL, AL
36425 JZ @@calldef
36427 CMP ESI, [Applet]
36428 JE @@calldef
36430 PUSH 0
36431 PUSH SC_MINIMIZE
36432 PUSH WM_SYSCOMMAND
36433 MOV EAX, [Applet]
36434 PUSH [EAX].TControl.fHandle
36435 CALL PostMessage
36436 JMP @@ret_0
36438 @@chk_WM_SETFOCUS:
36439 //CMP word ptr [EDI].TMsg.message, WM_SETFOCUS
36440 CMP AX, WM_SETFOCUS
36441 JNE @@chk_WM_SETCURSOR
36443 MOV EAX, ESI
36444 CALL TControl.DoSetFocus
36445 TEST AL, AL
36446 JZ @@0pass2defproc
36448 //@@calldef_clickdisabled:
36449 INC [ESI].TControl.fClickDisabled
36451 MOV EAX, ESI
36452 MOV EDX, EDI
36453 CALL TControl.CallDefWndProc
36455 DEC [ESI].TControl.fClickDisabled
36456 JMP @@exit
36458 @@chk_WM_SETCURSOR:
36459 //CMP word ptr [EDI].TMsg.message, WM_SETCURSOR
36460 CMP AX, WM_SETCURSOR
36461 JNE @@chk_WM_CTLCOLOR
36463 CMP [Global_DisableParentCursor], 0
36464 JNE @@calldef
36466 CALL GetCapture
36467 TEST EAX, EAX
36468 JNZ @@calldef
36470 CMP word ptr [EDI].TMsg.lParam, HTCLIENT
36471 JNE @@calldef
36473 MOV ECX, [ScreenCursor]
36474 INC ECX
36475 LOOP @@setupCursor
36477 MOV ECX, [ESI].TControl.fCursor
36478 TEST ECX, ECX //YS
36479 JE @@calldef //YS
36480 @@setupCursor:
36481 PUSH ECX
36482 CALL Windows.SetCursor
36484 MOV AL, 1
36485 JMP @@exit
36487 @@chk_WM_CTLCOLOR:
36488 //MOV EAX, [EDI].TMsg.message
36489 MOV EDX, EAX
36490 SUB DX, WM_CTLCOLORMSGBOX
36491 CMP DX, WM_CTLCOLORSTATIC-WM_CTLCOLORMSGBOX
36492 JA @@chk_WM_COMMAND
36494 PUSH [EDI].TMsg.lParam
36495 PUSH [EDI].TMsg.wParam
36496 ADD AX, CN_BASE //+WM_CTLCOLORMSGBOX
36497 PUSH EAX
36498 PUSH [EDI].TMsg.lParam
36499 CALL SendMessage
36500 JMP @@pass2defproc
36502 @@chk_WM_COMMAND:
36503 //CMP word ptr [EDI].TMsg.message, WM_COMMAND
36504 CMP AX, WM_COMMAND
36505 JNE @@chk_WM_KEY
36507 PUSH offset[ID_SELF]
36508 PUSH [EDI].TMsg.lParam
36509 CALL GetProp
36510 TEST EAX, EAX
36511 JZ @@calldef
36513 PUSH [EDI].TMsg.lParam
36514 PUSH [EDI].TMsg.wParam
36515 PUSH CM_COMMAND
36516 PUSH [EDI].TMsg.lParam
36517 CALL SendMessage
36518 JMP @@pass2defproc
36520 @@chk_WM_KEY:
36521 //MOV EAX, [EDI].TMsg.message
36522 MOV EDX, EAX
36523 SUB DX, WM_KEYFIRST
36524 CMP DX, WM_KEYLAST-WM_KEYFIRST
36525 JA @@chk_CM_EXECPROC
36527 CALL GetFocus
36528 CMP EAX, [ESI].TControl.fFocusHandle
36529 JE @@in_focus
36530 CMP EAX, [ESI].TControl.fHandle
36531 JNE @@0pass2defproc
36533 @@in_focus:
36534 PUSH EAX
36536 MOV ECX, ESP
36537 MOV EDX, EDI
36538 MOV EAX, ESI
36539 CALL dword ptr [fGlobalProcKeybd]
36540 TEST AL, AL
36541 JNZ @@to_exit
36543 MOV ECX, ESP
36544 MOV EDX, EDI
36545 MOV EAX, ESI
36546 CALL [ESI].fWndProcKeybd
36547 TEST AL, AL
36548 @@to_exit:
36549 POP EAX
36550 JNZ @@pass2defproc
36552 PUSH VK_CONTROL
36553 CALL GetKeyState
36554 XCHG EBX, EAX
36555 PUSH VK_MENU
36556 CALL GetKeyState
36557 OR EAX, EBX
36558 ADD EAX, EAX
36559 JC @@calldef
36561 CMP word ptr [EDI].TMsg.message, WM_CHAR
36562 JNE @@to_fGotoControl
36564 CMP byte ptr [EDI].TMsg.wParam, 9
36565 JE @@clear_wParam
36566 JMP @@calldef
36568 @@to_fGotoControl:
36569 MOV EAX, ESI
36570 CALL TControl.ParentForm
36571 TEST EAX, EAX
36572 JZ @@calldef
36574 MOV ECX, [EAX].fGotoControl
36575 JECXZ @@calldef
36577 MOV EBX, ECX
36578 CMP [EDI].TMsg.message, WM_KEYDOWN
36579 SETNE CL
36580 MOV EDX, [EDI].TMsg.wParam
36581 MOV EAX, ESI
36582 CALL EBX
36583 TEST AL, AL
36584 JZ @@calldef
36586 @@clear_wParam:
36587 XOR EAX, EAX
36588 MOV [EDI].TMsg.wParam, EAX
36589 JMP @@pass2defproc
36591 @@chk_CM_EXECPROC:
36592 //CMP word ptr [EDI].TMsg.message, CM_EXECPROC
36593 CMP AX, CM_EXECPROC
36594 JNE @@chk_MM_MCINOTIFY
36596 MOV EAX, [EDI].TMsg.lParam
36597 MOV EDX, [EDI].TMsg.wParam
36598 CALL [Global_Synchronized]
36599 JMP @@0pass2defproc
36601 @@chk_MM_MCINOTIFY:
36602 //CMP word ptr [EDI].TMsg.message, MM_MCINOTIFY
36603 CMP AX, MM_MCINOTIFY
36604 JNE @@calldef
36606 MOV ECX, [FMMNotify]
36607 JECXZ @@ret_0_MM
36609 XCHG EAX, EDI
36610 CALL ECX
36611 @@ret_0_MM:
36612 XOR EAX, EAX
36613 JMP @@exit
36615 @@calldef:
36616 XCHG EAX, ESI
36617 MOV EDX, EDI
36618 CALL TControl.CallDefWndProc
36619 JMP @@exit
36621 @@0pass2defproc:
36622 XOR EAX, EAX
36623 @@pass2defproc:
36624 PUSH EAX
36625 @@1pass2defproc:
36626 CMP [AppletTerminated], 0 //
36627 JNZ @@popeax_exit // uncommented 25-Oct-2003
36628 CMP [ESI].fNCDestroyed, 0 //
36629 JNZ @@popeax_exit //
36631 MOV ECX, ESP
36632 XCHG EAX, ESI
36633 MOV EDX, EDI
36634 CALL dword ptr[EAX].fPass2DefProc
36635 @@popeax_exit:
36636 POP EAX
36638 @@exit:
36639 POP EDI
36640 POP ESI
36641 POP EBX
36642 end;
36643 {$ELSE ASM_LOCAL} //Pascal
36645 {$IFDEF DEBUG_CREATEWINDOW}
36646 var DbgCWCount: Integer = 0;
36647 {$ENDIF DEBUG_CREATEWINDOW}
36648 function TControl.WndProc( var Msg: TMsg ): Integer;
36649 var Accept: Boolean;
36650 C : PControl;
36651 F {, Chld}: HWnd;
36652 Cur: HCURSOR; // YS
36653 PassFun: function( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
36655 procedure Default;
36656 begin
36657 Result := CallDefWndProc( Msg );
36658 end;
36660 begin
36661 {$IFDEF DEBUG_CREATEWINDOW}
36662 Inc( DbgCWCount );
36663 if DbgCWCount < 10 then
36664 LogFileOutput( GetStartDir + 'Session.log', 'TControl.WndProc: ' +
36665 ' Msg.hwnd=' + Int2Str( Msg.hwnd ) +
36666 ' Msg.message=' + Int2Hex( Msg.message, 2 ) +
36667 ' Msg.wParam=' + Int2Str( Msg.wParam ) + '=$' + Int2Hex( Msg.wParam, 4 ) +
36668 ' Msg.lParam=' + Int2Str( Msg.lParam ) + '=$' + Int2Hex( Msg.lParam, 4 ) );
36669 {$ENDIF DEBUG_CREATEWINDOW}
36670 if (Msg.hwnd <> 0) and (fHandle = 0) then
36671 fHandle := Msg.hwnd;
36673 PassFun := fPass2DefProc;
36674 if not Global_OnBufferedDraw( @Self, Msg, Result ) then
36675 if not (AppletRunning and (Applet <> @Self) and Assigned( Applet ) and
36676 Assigned( Applet.OnMessage ) and Applet.OnMessage( Msg, Result )) then
36677 if not (Assigned( OnMessage ) and OnMessage( Msg, Result )) then
36678 if not fOnDynHandlers( @Self, Msg, Result ) then
36679 begin
36680 if not fWndProcResizeFlicks( @Self, Msg, Result ) then
36681 case Msg.message of
36682 {$IFDEF NEW_MODAL}
36683 // version of code by Alexander Pravdin
36684 WM_CLOSE:
36685 begin
36686 Accept := True;
36687 if Assigned( fOnClose ) then begin
36688 fOnClose( @Self, Accept );
36689 if AppletRunning then
36690 if Accept then
36691 if fModal > 0 then begin
36692 if ModalResult = 0 then
36693 fModalResult := Integer($80000000);
36694 Msg.message := 0;
36695 Exit;
36697 else
36698 fOnClose := nil
36699 else begin
36700 Result := 0;
36701 fModalResult := 0;
36703 else
36704 fOnClose := nil;
36706 else begin
36707 if fModal > 0 then begin
36708 if ModalResult = 0 then
36709 fModalResult := Integer($80000000);
36710 Exit;
36711 end;
36712 end;
36714 if Accept then begin
36715 if IsMainWindow or ( Applet = @Self ) then begin
36716 if Assigned( Applet ) and ( Applet <> @Self ) then
36717 Applet.Perform( WM_CLOSE, 0, 0 );
36718 PostQuitMessage( 0 );
36719 Result := 0;
36721 else
36722 Default;
36723 end;
36724 end;
36725 {$ELSE}
36726 WM_CLOSE: begin
36727 Accept := True;
36728 if Assigned( fOnClose ) then
36729 begin
36730 fOnClose( @Self, Accept );
36731 if (not Accept) and (AppletRunning) then
36732 begin
36733 Result := 0;
36734 //ModalResult := 0;
36735 //Exit; //?????????????????
36737 else //+-+
36738 fOnClose := nil;
36739 end;
36740 if Accept then
36741 begin
36742 if IsMainWindow or (Applet = @Self) then
36743 begin
36744 if Assigned( Applet ) and (Applet <> @Self) then
36745 Applet.Perform( WM_CLOSE, 0, 0 );
36746 PostQuitMessage( 0 );
36747 Result := 0;
36748 //Exit; //???????????????
36750 else
36751 Default;
36752 end;
36753 end;
36754 {$ENDIF}
36755 {//********************************************************** Added By M.Gerasimov
36757 WM_DESTROY:
36758 begin
36759 Chld := GetWindow( fHandle, GW_CHILD );
36760 while Chld <> 0 do
36761 begin
36762 if GetProp( Chld, ID_PREVPROC ) <> 0 then
36763 RemoveProp(Chld, ID_PREVPROC);
36764 Chld := GetWindow( Chld, GW_HWNDNEXT );
36765 end;
36766 end;
36768 //********************************************************** Added By M.Gerasimov}
36769 WM_NCDESTROY:
36770 begin
36771 //********************************************************** Added By M.Gerasimov
36773 RemoveProp( fHandle, ID_SELF );
36775 //********************************************************** Added By M.Gerasimov
36776 if (Applet = nil) or (Handle <> Applet.Handle) then
36777 begin
36778 if IsMainWindow then
36779 begin
36780 PostMessage( fHandle, CM_RELEASE, 0, 0 );
36781 Default;
36783 else
36784 if fParent = Applet then
36785 begin
36786 fNCDestroyed := True;
36787 Free;
36788 Result := 0;
36789 Exit; //!!!!!!!!!!!!!!!!!!!!!!!!!
36791 else
36792 Default;
36793 end;
36794 end;
36796 CM_RELEASE: begin
36797 fDestroying := True;
36798 Free;
36799 Result := 0;
36800 //Exit; //??????????????????????????
36801 end;
36803 WM_SIZE: begin
36804 Default;
36805 case Msg.wParam of
36806 SIZENORMAL: fWindowState := wsNormal;
36807 SIZEICONIC: fWindowState := wsMinimized;
36808 SIZEFULLSCREEN: fWindowState := wsMaximized;
36809 end;
36810 if not fIsForm and (fParent <> nil) then
36811 Global_Align( fParent );
36812 Global_Align( @Self );
36813 Exit;
36814 end;
36815 WM_SHOWWINDOW:
36816 begin
36817 case Msg.lParam of
36818 SW_PARENTCLOSING:
36819 begin
36820 if IsIconic( fHandle ) then
36821 fShowAction := SW_SHOWMINNOACTIVE
36822 else
36823 if IsZoomed( fHandle ) then
36824 fShowAction := SW_SHOWMAXIMIZED
36825 else
36826 fShowAction := SW_SHOWNOACTIVATE;
36827 Default;
36828 end;
36829 SW_PARENTOPENING:
36830 begin
36831 if fShowAction <> 0 then
36832 begin
36833 ShowWindow( Handle, fShowAction );
36834 fShowAction := 0;
36835 end;
36836 Result := 0;
36837 //Exit; //?????????????????????????
36838 end;
36839 else Default;
36840 end;
36841 end;
36842 WM_SysCommand:
36843 begin
36844 if ((Msg.wParam and $FFF0) = SC_MINIMIZE) and
36845 IsMainWindow and (@Self <> Applet) then
36846 begin
36847 PostMessage( Applet.Handle, WM_SYSCOMMAND, SC_MINIMIZE, 0 );
36848 Result := 0;
36849 //Exit; //???????????????????????????
36851 else Default;
36852 end;
36853 WM_SETFOCUS:
36854 begin
36855 if not DoSetFocus then
36856 begin
36857 Result := 0;
36858 //Exit; //???????????????????????????
36860 else
36861 begin
36862 Inc( fClickDisabled );
36863 Default;
36864 Dec( fClickDisabled );
36865 Exit;
36866 end;
36867 end;
36868 WM_SETCURSOR:
36869 if not Global_DisableParentCursor then
36870 begin
36871 if (GetCapture = 0) and
36872 (LOWORD( Msg.lParam ) = HTCLIENT) then
36873 begin
36874 if ScreenCursor <> 0 then //YS
36875 Cur := ScreenCursor //YS
36876 else //YS
36877 Cur := fCursor; //YS
36878 if Cur <> 0 then //YS
36879 begin //YS
36880 Windows.SetCursor( Cur ); //YS
36881 Result := 1; //YS
36882 end //YS
36883 else //YS
36884 Default; //YS
36885 //Exit; //?????????????????????
36887 else Default;
36889 else Default;
36890 WM_CTLCOLORMSGBOX..WM_CTLCOLORSTATIC:
36891 begin
36892 Result := SendMessage(Msg.LParam, CN_BASE + Msg.message, Msg.WParam, Msg.LParam);
36893 //exit; //???????????????????????
36894 end;
36895 WM_COMMAND:
36896 begin
36897 C := Pointer( GetProp( Msg.lParam, ID_SELF ) );
36898 if C <> nil then
36899 begin
36900 Result := SendMessage( Msg.lParam, CM_COMMAND, Msg.wParam, Msg.lParam );
36901 //Exit; //???????????????????????
36903 else Default;
36904 end;
36905 WM_KEYFIRST..WM_KEYLAST:
36906 begin
36907 F := GetFocus;
36908 if (F <> fFocusHandle) and (F <> fHandle) then
36909 begin
36910 Result := 0;
36911 // Jump to PassFun here. Prevents beep in case when WM_KEYDOWN
36912 // called another form and focus is changed, so WM_KEYUP failed
36913 // to handle.
36915 else
36916 begin
36917 if fGlobalProcKeybd( @Self, Msg, Result ) then Exit; //??????????????????
36918 //else
36919 if fWndProcKeybd( @Self, Msg, Result ) then Exit; //???????????????????
36920 //else
36921 if ((GetKeystate( VK_CONTROL ) or GetKeyState( VK_MENU )) >= 0) then
36922 begin
36923 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
36924 if (Msg.message <> WM_CHAR) // v1.02 Tabulate AND " in EditBox fix
36925 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
36926 then
36927 begin
36928 C := ParentForm;
36929 if (C <> nil) and Assigned(C.fGotoControl) and
36930 C.fGotoControl( @Self, Msg.wParam, Msg.message <> WM_KEYDOWN ) then
36931 begin
36932 Msg.wParam := 0;
36933 Result := 0;
36934 //+-+exit;
36936 else Default;
36938 //+++++++++++++++++++++++++++++++++++++++++++++//
36939 else //
36940 if Msg.wParam = 9 then // prevent system beep //
36941 begin //
36942 Msg.wParam := 0; //
36943 Result := 0; //
36944 //+-+exit; //
36945 end //
36946 //+++++++++++++++++++++++++++++++++++++++++++++//
36947 else Default;
36949 else Default;
36950 end;
36951 end;
36952 CM_EXECPROC: begin
36953 Global_Synchronized( Pointer( Msg.lParam ), Pointer( Msg.wParam ) );
36954 Result := 0;
36955 //Exit; //???????????????????
36956 end;
36957 MM_MCINOTIFY: begin
36958 if Assigned( FMMNotify ) then
36959 FMMNotify( Msg );
36960 Result := 0;
36961 exit;
36962 end;
36963 else begin
36964 Default; //+-+
36965 Exit; //+-+
36966 end;
36967 end;
36968 end;
36970 if not AppletTerminated and not fNCDestroyed then
36971 PassFun( @Self, Msg, Result ); //+-+
36972 end;
36973 {$ENDIF ASM_LOCAL}
36974 //[END TContro]
36976 {$UNDEF ASM_LOCAL}
36978 //[procedure SetMouseEvent]
36979 procedure SetMouseEvent( Self_: PControl );
36980 begin
36981 Self_.AttachProc( WndProcMouse );
36982 end;
36984 //[procedure TControl.SetMouseDown]
36985 procedure TControl.SetMouseDown(const Value: TOnMouse);
36986 begin
36987 fOnMouseDown := Value;
36988 SetMouseEvent( @Self );
36989 end;
36991 //[procedure TControl.SetMouseMove]
36992 procedure TControl.SetMouseMove(const Value: TOnMouse);
36993 begin
36994 fOnMouseMove := Value;
36995 SetMouseEvent( @Self );
36996 end;
36998 //[procedure TControl.SetMouseUp]
36999 procedure TControl.SetMouseUp(const Value: TOnMouse);
37000 begin
37001 fOnMouseUp := Value;
37002 SetMouseEvent( @Self );
37003 end;
37005 //[procedure TControl.SetMouseDblClk]
37006 procedure TControl.SetMouseDblClk(const Value: TOnMouse);
37007 begin
37008 fOnMouseDblClk := Value;
37009 SetMouseEvent( @Self );
37010 end;
37012 //[procedure TControl.SetMouseWheel]
37013 procedure TControl.SetMouseWheel(const Value: TOnMouse);
37014 begin
37015 fOnMouseWheel := Value;
37016 SetMouseEvent( @Self );
37017 end;
37019 {$IFDEF ASM_VERSION}
37020 //[procedure TControl.SetClsStyle]
37021 procedure TControl.SetClsStyle( Value: DWord );
37022 asm //cmd //opd
37023 CMP EDX, [EAX].TControl.fClsStyle
37024 JE @@exit
37025 MOV [EAX].TControl.fClsStyle, EDX
37026 MOV ECX, [EAX].TControl.fHandle
37027 JECXZ @@exit
37028 PUSH EDX
37029 PUSH GCL_STYLE
37030 PUSH ECX
37031 CALL SetClassLong
37032 @@exit:
37033 end;
37034 {$ELSE ASM_VERSION} //Pascal
37035 procedure TControl.SetClsStyle( Value: DWord );
37036 begin
37037 if fClsStyle = Value then Exit;
37038 fClsStyle := Value;
37039 if fHandle = 0 then Exit;
37040 SetClassLong( fHandle, GCL_STYLE, Value );
37041 end;
37042 {$ENDIF ASM_VERSION}
37044 {$IFDEF ASM_VERSION}
37045 //[procedure TControl.SetStyle]
37046 procedure TControl.SetStyle( Value: DWord );
37047 const SWP_FLAGS = SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or
37048 SWP_NOZORDER or SWP_FRAMECHANGED;
37050 CMP EDX, [EAX].fStyle
37051 JZ @@exit
37052 MOV [EAX].fStyle, EDX
37053 MOV ECX, [EAX].fHandle
37054 JECXZ @@exit
37056 PUSH EAX
37058 PUSH SWP_FLAGS
37059 XOR EAX, EAX
37060 PUSH EAX
37061 PUSH EAX
37062 PUSH EAX
37063 PUSH EAX
37064 PUSH EAX
37065 PUSH ECX
37067 PUSH EDX
37068 PUSH GWL_STYLE
37069 PUSH ECX
37070 CALL SetWindowLong
37072 CALL SetWindowPos
37074 POP EAX
37075 CALL Invalidate
37076 @@exit:
37077 end;
37078 {$ELSE ASM_VERSION} //Pascal
37079 procedure TControl.SetStyle( Value: DWord );
37080 begin
37081 if fStyle = Value then Exit;
37082 fStyle := Value;
37083 if fHandle = 0 then Exit;
37084 SetWindowLong( fHandle, GWL_STYLE, Value );
37086 SetWindowPos( fHandle, 0, 0, 0, 0, 0,
37087 SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or
37088 SWP_NOZORDER or SWP_FRAMECHANGED );
37089 Invalidate;
37090 end;
37091 {$ENDIF ASM_VERSION}
37093 {$IFDEF ASM_VERSION}
37094 //[procedure TControl.SetExStyle]
37095 procedure TControl.SetExStyle( Value: DWord );
37096 const SWP_FLAGS = SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or
37097 SWP_NOZORDER or SWP_FRAMECHANGED;
37099 CMP EDX, [EAX].fExStyle
37100 JZ @@exit
37101 MOV [EAX].fExStyle, EDX
37102 MOV ECX, [EAX].fHandle
37103 JECXZ @@exit
37105 PUSH EAX
37107 PUSH SWP_FLAGS
37108 XOR EAX, EAX
37109 PUSH EAX
37110 PUSH EAX
37111 PUSH EAX
37112 PUSH EAX
37113 PUSH EAX
37114 PUSH ECX
37116 PUSH EDX
37117 PUSH GWL_EXSTYLE
37118 PUSH ECX
37119 CALL SetWindowLong
37121 CALL SetWindowPos
37123 POP EAX
37124 CALL Invalidate
37125 @@exit:
37126 end;
37127 {$ELSE ASM_VERSION} //Pascal
37128 procedure TControl.SetExStyle( Value: DWord );
37129 begin
37130 if fExStyle = Value then Exit;
37131 fExStyle := Value;
37132 if fHandle = 0 then Exit;
37133 SetWindowLong( fHandle, GWL_EXSTYLE, Value );
37135 SetWindowPos( fHandle, 0, 0, 0, 0, 0,
37136 SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or
37137 SWP_NOZORDER or SWP_FRAMECHANGED );
37138 Invalidate;
37139 end;
37140 {$ENDIF ASM_VERSION}
37142 {$IFDEF ASM_VERSION}
37143 //[procedure TControl.SetCursor]
37144 procedure TControl.SetCursor( Value: HCursor );
37145 asm //cmd //opd
37146 CMP EDX, [EAX].TControl.fCursor
37147 JE @@exit
37148 MOV [EAX].TControl.fCursor, EDX
37149 MOV ECX, [EAX].TControl.fHandle
37150 JECXZ @@exit
37151 TEST EDX, EDX //YS
37152 JE @@exit //YS
37153 MOV ECX, [ScreenCursor]
37154 INC ECX
37155 LOOP @@exit
37157 PUSH EBX
37158 XCHG EBX, EAX
37159 PUSH EDX
37160 PUSH EAX
37161 PUSH EAX
37162 PUSH ESP
37163 CALL GetCursorPos
37164 MOV EDX, ESP
37165 MOV ECX, EDX
37166 MOV EAX, EBX
37167 CALL Screen2Client
37168 ADD ESP, -16
37169 MOV EDX, ESP
37170 MOV EAX, EBX
37171 CALL TControl.ClientRect
37172 MOV EDX, ESP
37173 LEA EAX, [ESP+16]
37174 CALL PointInRect
37175 ADD ESP, 24
37176 TEST AL, AL
37177 JZ @@fin
37178 CALL Windows.SetCursor
37179 PUSH EAX
37180 @@fin: POP EAX
37181 POP EBX
37182 @@exit:
37183 end;
37184 {$ELSE ASM_VERSION} //Pascal
37185 procedure TControl.SetCursor( Value: HCursor );
37186 var P: TPoint;
37187 begin
37188 if fCursor = Value then Exit;
37189 fCursor := Value;
37190 if (fHandle = 0) or (fCursor = 0) then Exit; //YS
37191 if ScreenCursor <> 0 then Exit;
37192 GetCursorPos( P );
37193 P := Screen2Client( P );
37194 if PointInRect( P, ClientRect ) then
37195 Windows.SetCursor( Value );
37196 end;
37197 {$ENDIF ASM_VERSION}
37199 //[procedure TControl.CursorLoad]
37200 procedure TControl.CursorLoad(Inst: Integer; ResName: PChar);
37201 begin
37202 Cursor := LoadCursor( Inst, ResName );
37203 fCursorShared := TRUE;
37204 end;
37206 {$IFDEF ASM_VERSION}
37207 //[procedure TControl.SetIcon]
37208 procedure TControl.SetIcon( Value: HIcon );
37209 asm //cmd //opd
37210 CMP EDX, [EAX].TControl.fIcon
37211 JE @@exit
37212 MOV [EAX].TControl.fIcon, EDX
37213 INC EDX
37214 JZ @@1
37215 DEC EDX
37216 @@1:
37217 PUSH EDX
37218 PUSH 1 //ICON_BIG
37219 PUSH WM_SETICON
37220 PUSH EAX
37221 CALL Perform
37222 TEST EAX, EAX
37223 JZ @@exit
37224 PUSH EAX
37225 CALL DestroyIcon
37226 @@exit:
37227 end;
37228 {$ELSE ASM_VERSION} //Pascal
37229 procedure TControl.SetIcon( Value: HIcon );
37230 var OldIco: HIcon;
37231 begin
37232 if fIcon = Value then Exit;
37233 fIcon := Value;
37234 if Value = THandle(-1) then
37235 Value := 0;
37236 OldIco := Perform( WM_SETICON, 1 {ICON_BIG}, Value );
37237 if OldIco <> 0 then
37238 DestroyIcon( OldIco );
37239 end;
37240 {$ENDIF ASM_VERSION}
37242 {$IFDEF ASM_VERSION}
37243 //[procedure TControl.SetMenu]
37244 procedure TControl.SetMenu( Value: HMenu );
37246 PUSH EBX
37247 XCHG EBX, EAX
37248 CMP [EBX].fMenu, EDX
37249 JZ @@exit
37250 PUSH EDX
37251 MOV ECX, [EBX].fMenuObj
37252 JECXZ @@no_free_menuctl
37253 XCHG EAX, EDX
37254 CALL TObj.Free
37255 @@no_free_menuctl:
37256 MOV ECX, [EBX].fMenu
37257 JECXZ @@no_destroy
37258 PUSH ECX
37259 CALL DestroyMenu
37260 @@no_destroy:
37261 POP EDX
37262 MOV [EBX].fMenu, EDX
37263 MOV ECX, [EBX].fHandle
37264 JECXZ @@exit
37265 PUSH EDX
37266 PUSH ECX
37267 CALL Windows.SetMenu
37268 @@exit:
37269 POP EBX
37270 end;
37271 {$ELSE ASM_VERSION} //Pascal
37272 procedure TControl.SetMenu( Value: HMenu );
37273 begin
37274 if fMenu = Value then Exit;
37275 if fMenuObj <> nil then
37276 fMenuObj.Free;
37277 if fMenu <> 0 then
37278 DestroyMenu( fMenu );
37279 fMenu := Value;
37280 if fHandle = 0 then Exit;
37281 Windows.SetMenu( fHandle, Value );
37282 end;
37283 {$ENDIF ASM_VERSION}
37285 //[procedure CallWinHelp]
37286 procedure CallWinHelp( Context: Integer; CtxCtl: PControl );
37287 var Cmd: Integer;
37288 Form: PControl;
37289 Popup: Boolean;
37290 begin
37291 Cmd := HELP_CONTEXT;
37292 if CtxCtl <> nil then
37293 begin
37294 Form := CtxCtl.ParentForm;
37295 if Form <> nil then
37296 if Assigned( Form.OnHelp ) then
37297 begin
37298 Popup := FALSE;
37299 Form.OnHelp( CtxCtl, Context, Popup );
37300 if Popup then
37301 Cmd := HELP_CONTEXTPOPUP;
37302 if CtxCtl = nil then Exit;
37303 end;
37305 else
37306 if Context = 0 then
37307 Cmd := HELP_CONTENTS;
37308 WinHelp( Applet.Handle, PChar( Applet.GetHelpPath ), Cmd, Context );
37309 end;
37311 var HHCtrl: THandle;
37312 HtmlHelp: procedure( Wnd: HWnd; Path: PChar; Cmd, Data: Integer ); stdcall;
37314 //[procedure HtmlHelpCommand]
37315 procedure HtmlHelpCommand( Wnd: HWnd; const HelpFilePath: String; Cmd, Data: Integer );
37316 begin
37317 if HHCtrl = 0 then
37318 HHCtrl := LoadLibrary( 'HHCTRL.OCX' );
37319 if HHCtrl = 0 then Exit;
37320 if not Assigned( HtmlHelp ) then
37321 HtmlHelp := GetProcAddress( HHCtrl, 'HtmlHelpA' );
37322 if not Assigned( HtmlHelp ) then Exit;
37323 HtmlHelp( Wnd, PChar( HelpFilePath ), Cmd, Data );
37324 end;
37326 //[procedure CallHtmlHelp]
37327 procedure CallHtmlHelp( Context: Integer; CtxCtl: PControl );
37328 var Cmd: Integer;
37329 Form: PControl;
37330 Popup: Boolean;
37331 Ids: array[ 0..2 ] of DWORD;
37332 begin
37334 Cmd := $F; // HH_HELP_CONTEXT;
37335 if CtxCtl <> nil then
37336 begin
37337 Form := CtxCtl.ParentForm;
37338 if Form <> nil then
37339 if Assigned( Form.OnHelp ) then
37340 begin
37341 Popup := FALSE;
37342 Form.OnHelp( CtxCtl, Context, Popup );
37343 if Popup then
37344 begin
37345 Cmd := $10; //HH_TP_HELPCONTEXTMENU;
37346 Ids[ 0 ] := CtxCtl.fMenu;
37347 Ids[ 1 ] := Context;
37348 Ids[ 2 ] := 0;
37349 Context := Integer( @ Ids );
37350 end;
37351 if CtxCtl = nil then Exit;
37352 end;
37354 else
37355 if Context = 0 then
37356 Cmd := 1; // HH_DISPLAY_TOC;
37357 HtmlHelpCommand( Applet.Handle, HelpFilePath, Cmd, Context );
37358 end;
37361 Global_HelpProc: procedure( Context: Integer; CtxCtl: PControl ) = CallWinHelp;
37363 //[function WndProcHelp]
37364 function WndProcHelp( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
37365 var HI: PHelpInfo;
37366 Ctx: Integer;
37367 Ctl: PControl;
37368 begin
37369 Result := FALSE;
37370 if Msg.message = WM_HELP then
37371 begin
37372 Ctx := 0;
37373 Ctl := nil;
37374 HI := Pointer( Msg.lParam );
37375 if HI.iContextType = HELPINFO_WINDOW then
37376 begin
37377 Ctl := Pointer( GetProp( HI.hItemHandle, ID_SELF ) );
37378 while Ctl <> nil do
37379 begin
37380 Ctx := Ctl.fHelpContext;
37381 if Ctx <> 0 then break;
37382 Ctl := Ctl.Parent;
37383 end;
37385 else
37386 //if HI.iContextType = HELPINFO_MENUITEM then
37387 Ctx := GetMenuContextHelpID( HI.hItemHandle );
37388 Applet.CallHelp( Ctx, Ctl );
37389 Rslt := 1;
37390 Result := TRUE;
37392 {$IFDEF AUTO_CONTEXT_HELP}
37393 else
37394 if (Msg.message = WM_CONTEXTMENU) then
37395 begin
37396 Ctl := Pointer( GetProp( Msg.wParam, ID_SELF ) );
37397 if (Ctl <> nil) and (Ctl.fHelpContext <> 0) then
37398 //if (Ctl.fAutoPopupMenu = nil) then // seems not working
37399 begin
37400 Applet.CallHelp( Ctl.fHelpContext, Ctl );
37401 Rslt := 1;
37402 Result := TRUE;
37403 end;
37405 {$ENDIF}
37407 end;
37409 //[procedure TControl.SetHelpContext]
37410 procedure TControl.SetHelpContext(Value: Integer);
37411 var F: PControl;
37412 begin
37413 fHelpContext := Value;
37414 F := ParentForm;
37415 if F = nil then Exit;
37416 F.AttachProc( WndProcHelp );
37417 SetWindowContextHelpId( GetWindowHandle, Value );
37418 end;
37420 //[function TControl.AssignHelpContext]
37421 function TControl.AssignHelpContext(Context: Integer): PControl;
37422 begin
37423 SetHelpContext( Context );
37424 Result := @ Self;
37425 end;
37427 //[procedure AssignHtmlHelp]
37428 procedure AssignHtmlHelp( const HtmlHelpPath: String );
37429 begin
37430 Assert( (HtmlHelpPath <> '') and (Applet <> nil), 'Error parameters' );
37431 if HelpFilePath <> '' then
37432 FreeMem( HelpFilePath );
37433 GetMem( HelpFilePath, Length( HtmlHelpPath ) + 1 );
37434 StrCopy( HelpFilePath, @ HtmlHelpPath[ 1 ] );
37435 Global_HelpProc := CallHtmlHelp;
37436 Applet.AttachProc( WndProcHelp );
37437 end;
37439 //[procedure TControl.CallHelp]
37440 procedure TControl.CallHelp(Context: Integer; CtxCtl: PControl {; CtlID: Integer} );
37441 begin
37442 Global_HelpProc( Context, CtxCtl {, CtlID} );
37443 end;
37445 //[function TControl.GetHelpPath]
37446 function TControl.GetHelpPath: String;
37447 begin
37448 Result := HelpFilePath;
37449 if Result = '' then
37450 begin
37451 Result := ParamStr( 0 );
37452 Result := ReplaceFileExt( Result, '.hlp' );
37453 end;
37454 end;
37456 //[procedure TControl.SetHelpPath]
37457 procedure TControl.SetHelpPath(const Value: String);
37458 begin
37459 Assert( Value <> '', 'Error parameter' );
37460 if HelpFilePath <> '' then
37461 FreeMem( HelpFilePath );
37462 GetMem( HelpFilePath, Length( Value ) + 1 );
37463 StrCopy( HelpFilePath, @ Value[ 1 ] );
37464 end;
37466 {$IFDEF ASM_VERSION}
37467 //[function TControl.GetCaption]
37468 function TControl.GetCaption: String;
37470 XCHG EAX, EDX
37471 MOVZX ECX, [EDX].fIgnoreWndCaption
37472 JECXZ @@getwndcaption
37474 @@ret_fCaption:
37475 MOV EDX, [EDX].fCaption
37476 JMP System.@LStrFromPChar
37478 @@getwndcaption:
37479 MOV ECX, [EDX].fHandle
37480 JECXZ @@ret_fCaption
37482 PUSH EBX
37483 PUSH ESI
37484 XCHG EBX, EAX
37486 MOV ESI, ECX
37487 PUSH ESI
37488 CALL GetWindowTextLength
37489 MOV EDX, EAX
37490 INC EAX
37491 PUSH EAX // MaxLen
37493 MOV EAX, EBX
37494 CALL System.@LStrSetLength
37496 POP EDX
37497 MOV ECX, [EBX]
37498 JECXZ @@exit
37499 PUSH EDX // MaxLen = Length(Result) + 1
37501 PUSH ECX //@Result[1]
37502 PUSH ESI // fHandle
37503 CALL GetWindowText
37505 @@exit:
37506 POP ESI
37507 POP EBX
37508 end;
37509 {$ELSE ASM_VERSION} //Pascal
37510 function TControl.GetCaption: String;
37511 var Buf: PChar;
37512 Sz: Integer;
37513 begin
37514 if not fIgnoreWndCaption and (FHandle <> 0) then
37515 begin
37516 Sz := GetWindowTextLength( FHandle );
37517 if Sz = 0 then
37518 Buf := nil
37519 else
37520 begin
37521 GetMem( Buf, Sz + 1 );
37522 GetWindowText( FHandle, Buf, Sz + 1 );
37523 end;
37524 Result := Buf;
37525 if Buf <> nil then
37526 FreeMem( Buf );
37527 Exit;
37528 end;
37529 Result := FCaption;
37530 end;
37531 {$ENDIF ASM_VERSION}
37533 {$IFDEF ASM_VERSION}
37534 //[procedure TControl.SetCaption]
37535 procedure TControl.SetCaption( const Value: String );
37537 PUSH EBX
37538 XCHG EBX, EAX
37539 PUSH EDX
37540 MOV EAX, [EBX].fCaption
37541 TEST EAX, EAX
37542 JZ @@store_Caption
37543 CALL System.@FreeMem
37544 @@store_Caption:
37545 POP EAX
37546 CALL EAX2PChar
37547 PUSH EAX
37548 CALL StrLen
37549 INC EAX
37550 CALL System.@GetMem
37551 MOV [EBX].fCaption, EAX
37552 POP EDX
37553 CALL StrCopy
37554 MOV ECX, [EBX].fHandle
37555 JECXZ @@exit
37556 PUSH [EBX].fCaption
37557 PUSH ECX
37558 CALL SetWindowText
37559 CMP [EBX].fIsStaticControl, 0
37560 JZ @@1
37561 MOV EAX, EBX
37562 CALL Invalidate
37563 @@1:
37564 XCHG EAX, EBX
37565 MOV ECX, [EAX].fAutoSize
37566 JECXZ @@exit
37567 CALL ECX
37568 @@exit: POP EBX
37569 end;
37570 {$ELSE ASM_VERSION} //Pascal
37571 procedure TControl.SetCaption( const Value: String );
37572 var L: DWORD;
37573 begin
37574 //if fHandle = 0 then
37575 begin
37576 if fCaption <> nil then
37577 FreeMem( fCaption );
37578 L := Length( Value ) + 1;
37579 GetMem( fCaption, L );
37580 StrCopy( fCaption, PChar( Value ) );
37581 //Exit;
37582 end;
37583 if fHandle = 0 then Exit;
37584 SetWindowText( fHandle, @Value[ 1 ] );
37585 if not fIsStaticControl then
37586 Invalidate;
37587 if Assigned( fAutoSize ) then
37588 fAutoSize( @Self );
37589 end;
37590 {$ENDIF ASM_VERSION}
37592 {$IFDEF ASM_VERSION}
37593 //[function TControl.GetVisible]
37594 function TControl.GetVisible: Boolean;
37596 MOV ECX, [EAX].fHandle
37597 JECXZ @@check_fStyle
37599 {CMP [EAX].fIsControl, 0
37600 JNE @@check_fStyle}
37602 PUSH EAX
37603 PUSH ECX
37604 CALL IsWindowVisible
37605 TEST EAX, EAX
37606 POP EAX
37607 JMP @@checked // Z if not visible
37609 @@check_fStyle:
37610 TEST byte ptr [EAX].fStyle+3, 10h // WS_VISIBLE shr 3
37611 @@checked:
37612 SETNZ DL
37613 MOV [EAX].fVisible, DL
37614 XCHG EAX, EDX
37615 end;
37616 {$ELSE ASM_VERSION}
37617 function TControl.GetVisible: Boolean;
37618 begin
37619 if (fHandle <> 0)
37620 //and (not fIsControl or (ParentForm <> nil) and ParentForm.Visible)
37621 //and not fIsControl
37622 then
37623 fVisible :=
37624 //LongBool( GetWindowLong( fHandle, GWL_STYLE ) and WS_VISIBLE )
37625 IsWindowVisible( fHandle )
37626 else
37627 fVisible := (FStyle and WS_VISIBLE) <> 0;
37628 Result := fVisible;
37629 end;
37630 {$ENDIF ASM_VERSION}
37632 {$IFDEF ASM_VERSION}
37633 //[function TControl.Get_Visible]
37634 function TControl.Get_Visible: Boolean;
37635 asm // //
37636 MOV ECX, [EAX].fHandle
37637 JECXZ @@ret_fVisible
37638 CMP [EAX].fIsControl, 0
37639 JNZ @@ret_fVisible
37640 PUSH EAX
37641 PUSH ECX
37642 CALL IsWindowVisible
37643 XCHG EDX, EAX
37644 POP EAX
37645 MOV [EAX].fVisible, DL
37646 @@ret_fVisible:
37647 MOVZX EAX, [EAX].fVisible
37648 end;
37649 {$ELSE ASM_VERSION} // Pascal
37650 function TControl.Get_Visible: Boolean;
37651 begin
37652 if (fHandle <> 0)
37653 //and (not fIsControl or (ParentForm <> nil) and ParentForm.Visible)
37654 and not fIsControl
37655 then
37656 fVisible :=
37657 //LongBool( GetWindowLong( fHandle, GWL_STYLE ) and WS_VISIBLE )
37658 IsWindowVisible( fHandle );
37659 Result := fVisible;
37660 end;
37661 {$ENDIF ASM_VERSION}
37663 {$IFDEF ASM_VERSION}
37664 //[procedure TControl.Set_Visible]
37665 procedure TControl.Set_Visible( Value: Boolean );
37666 const wsVisible = $10;
37668 PUSH EBX
37669 PUSH ESI
37670 //MOV ESI, EAX
37671 XCHG ESI, EAX
37672 MOVZX EBX, DL
37673 {CALL Get_Visible
37674 CMP AL, BL
37675 JE @@reset_fCreateHidden}
37677 MOV AL, byte ptr [ESI].fStyle + 3
37678 TEST EBX, EBX
37679 JZ @@reset_WS_VISIBLE
37680 OR AL, wsVisible
37681 PUSH SW_SHOW
37682 JMP @@store_Visible
37683 @@reset_WS_VISIBLE:
37684 AND AL, not wsVisible
37685 PUSH SW_HIDE
37687 @@store_Visible:
37688 MOV byte ptr [ESI].fStyle + 3, AL
37689 MOV [ESI].fVisible, BL
37690 MOV ECX, [ESI].fHandle
37691 JECXZ @@after_showwindow
37693 PUSH ECX
37694 CALL ShowWindow
37695 PUSH ECX
37696 @@after_showwindow:
37697 POP ECX
37699 MOV ECX, [ESI].fParent
37700 JECXZ @@chk_align_Self
37701 XCHG EAX, ECX
37702 CALL dword ptr [Global_Align]
37704 @@chk_align_Self:
37705 TEST EBX, EBX
37706 JZ @@reset_fCreateHidden
37707 MOV EAX, ESI
37708 CALL dword ptr [Global_Align]
37711 @@reset_fCreateHidden:
37712 MOV ECX, [ESI].fHandle
37713 JECXZ @@exit
37714 TEST BL, BL
37715 JNZ @@exit
37716 MOV [ESI].fCreateHidden, 0 { +++ }
37717 @@exit:
37718 POP ESI
37719 POP EBX
37720 end;
37721 {$ELSE ASM_VERSION} // Pascal
37722 procedure TControl.Set_Visible( Value: Boolean );
37723 var CmdShow: DWORD;
37724 begin
37725 //if Get_Visible <> Value then // commented to allow to set up controls visibility
37726 begin // on invisible form (Vladimir Piven)
37727 if Value then
37728 begin
37729 fStyle := fStyle or WS_VISIBLE;
37730 CmdShow := SW_SHOW;
37732 else
37733 begin
37734 fStyle := fStyle and not WS_VISIBLE;
37735 CmdShow := SW_HIDE;
37736 end;
37737 fVisible := Value;
37738 if fHandle = 0 then Exit;
37739 ShowWindow( fHandle, CmdShow );
37740 if fParent <> nil then
37741 Global_Align( fParent );
37742 //else
37743 if Value then
37744 Global_Align( @Self );
37745 end;
37746 if not Value and (fHandle <> 0) then
37747 fCreateHidden := FALSE; // { +++ }
37748 end;
37749 {$ENDIF ASM_VERSION}
37751 //[procedure TControl.SetVisible]
37752 procedure TControl.SetVisible( Value: Boolean );
37753 begin
37754 fCreateVisible := TRUE;
37755 Set_Visible( Value );
37756 end;
37758 {$IFDEF ASM_VERSION}
37759 //[function TControl.GetBoundsRect]
37760 function TControl.GetBoundsRect: TRect;
37762 PUSH ESI
37763 PUSH EDI
37764 LEA ESI, [EAX].fBoundsRect
37765 MOV EDI, EDX
37767 PUSH EDX
37769 MOVSD
37770 MOVSD
37771 MOVSD
37772 MOVSD
37774 POP EDI
37776 XCHG ESI, EAX
37777 MOV ECX, [ESI].fHandle
37778 JECXZ @@exit
37780 PUSH EDI
37781 PUSH ECX
37782 CALL GetWindowRect
37784 CMP [ESI].fIsControl, 0
37785 JZ @@storeBounds
37787 MOV EAX, [ESI].fParent
37789 TEST EAX, EAX
37790 JZ @@exit
37792 XOR EDX, EDX
37793 PUSH EDX
37794 PUSH EDX
37795 MOV ECX, ESP
37796 PUSH EDX
37797 PUSH EDX
37798 MOV EDX, ESP
37799 CALL TControl.Client2Screen
37800 POP EAX
37801 POP EAX
37803 POP EAX
37804 NEG EAX
37805 POP ECX
37806 NEG ECX
37807 PUSH ECX
37808 PUSH EAX
37809 PUSH EDI
37810 CALL OffsetRect
37812 @@storeBounds:
37813 XCHG ESI, EDI
37814 LEA EDI, [EDI].fBoundsRect
37815 MOVSD
37816 MOVSD
37817 MOVSD
37818 MOVSD
37820 @@exit:
37821 POP EDI
37822 POP ESI
37823 end;
37824 {$ELSE ASM_VERSION} //Pascal
37825 function TControl.GetBoundsRect: TRect;
37826 var W: PControl;
37827 P: TPoint;
37828 begin
37829 Result := fBoundsRect;
37830 if fHandle <> 0 then
37831 begin
37832 GetWindowRect( fHandle, Result );
37833 if fIsControl then
37834 begin
37835 W := fParent; // WindowedParent;
37836 if W <> nil then
37837 begin
37838 P.x := 0; P.y := 0;
37839 P := W.Client2Screen( P );
37840 OffsetRect( Result, -P.x, -P.y );
37841 end;
37842 end;
37843 fBoundsRect := Result;
37844 end;
37845 end;
37846 {$ENDIF ASM_VERSION}
37848 //[PROCEDURE HelpGetBoundsRect]
37849 {$IFDEF ASM_VERSION}
37850 procedure HelpGetBoundsRect;
37852 POP ECX
37853 ADD ESP, - size_TRect
37854 MOV EDX, ESP
37855 PUSH ECX
37856 PUSH EAX
37857 CALL TControl.GetBoundsRect
37858 POP EAX
37859 end;
37860 {$ENDIF ASM_VERSION}
37861 //[END HelpGetBoundsRect]
37863 {$IFDEF ASM_VERSION}
37864 //[procedure TControl.SetBoundsRect]
37865 procedure TControl.SetBoundsRect( const Value: TRect );
37866 const swp_flags = SWP_NOZORDER or SWP_NOACTIVATE;
37868 PUSH EDI
37869 MOV EDI, EAX
37871 PUSH ESI
37872 MOV ESI, EDX
37874 CALL HelpGetBoundsRect
37876 MOV EAX, ESI
37877 MOV EDX, ESP
37878 CALL RectsEqual
37879 TEST AL, AL
37880 JNZ @@exit
37882 POP EDX // left
37883 POP ECX // top
37884 POP EAX // right
37885 PUSH EAX
37886 PUSH ECX
37887 PUSH EDX
37889 SUB EAX, EDX // EAX = width
37890 CMP EDX, [ESI].TRect.Left
37891 MOV DL, 0
37892 JE @@1
37893 INC EDX
37894 @@1: CMP ECX, [ESI].TRect.Top
37895 JE @@2
37896 OR DL, 2
37897 @@2: OR [EDI].fChangedPosSz, DL
37899 PUSH EAX // W saved
37901 MOV EAX, [EDI].fBoundsRect.Bottom
37902 SUB EAX, ECX
37903 PUSH EAX // H saved
37905 PUSH EDI // @Self saved
37907 LEA EDI, [EDI].fBoundsRect
37908 MOVSD
37909 MOVSD
37910 MOVSD
37911 MOVSD
37913 MOV ESI, EDI
37914 POP EDI // @ Self restored
37915 MOV ECX, [EDI].fHandle
37916 JECXZ @@fin
37920 PUSH swp_flags
37922 LODSD
37923 LODSD
37924 XCHG EDX, EAX // EDX = bottom
37925 LODSD
37926 XCHG ECX, EAX // ECX = right
37927 LODSD
37928 SUB EDX, EAX // EAX = bottom - top
37929 PUSH EDX // push HEIGHT
37930 XCHG EDX, EAX // EDX = top
37931 LODSD // EAX = left
37934 SUB ECX, EAX
37935 PUSH ECX // push WIDTH
37937 PUSH EDX // push TOP
37938 PUSH EAX // push LEFT
37939 PUSH 0
37941 PUSH [EDI].fHandle
37942 CALL SetWindowPos
37944 CMP [EDI].fSizeRedraw, 0
37945 JE @@fin
37946 XCHG EAX, EDI
37947 CALL Invalidate // *MUST* be called?
37949 @@fin:
37950 POP EDX // H restored
37951 POP EAX // W restored
37953 @@exit:
37954 ADD ESP, size_TRect
37955 POP ESI
37956 POP EDI
37957 end;
37958 {$ELSE ASM_VERSION} //Pascal
37959 procedure TControl.SetBoundsRect( const Value: TRect );
37960 var Rect: TRect;
37961 begin
37962 Rect := GetBoundsRect;
37963 if RectsEqual( Value, Rect ) then Exit;
37964 if Value.Left <> fBoundsRect.Left then fChangedPosSz := fChangedPosSz or 1;
37965 if Value.Top <> fBoundsRect.Top then fChangedPosSz := fChangedPosSz or 2;
37966 fBoundsRect := Value;
37967 Rect := Value;
37969 if fHandle <> 0 then
37970 begin
37971 SetWindowPos( fHandle, 0, Rect.Left, Rect.Top, Rect.Right - Rect.Left,
37972 Rect.Bottom - Rect.Top, SWP_NOZORDER or SWP_NOACTIVATE );
37973 if fSizeRedraw then
37974 Invalidate;
37975 end;
37976 end;
37977 {$ENDIF ASM_VERSION}
37979 const
37980 WindowStateShowCommands: array[TWindowState] of Byte =
37981 (SW_SHOWNOACTIVATE, SW_SHOWMINNOACTIVE, SW_SHOWMAXIMIZED);
37982 {$IFDEF ASM_VERSION}
37983 //[procedure TControl.SetWindowState]
37984 procedure TControl.SetWindowState( Value: TWindowState );
37985 asm //cmd //opd
37986 CMP [EAX].TControl.fWindowState, DL
37987 JE @@exit
37988 MOV [EAX].TControl.fWindowState, DL
37989 XCHG EAX, EDX
37991 CWDE
37992 MOV AL, byte ptr [WindowStateShowCommands+EAX]
37993 PUSH EAX
37994 XCHG EAX, EDX
37995 CALL TControl.GetWindowHandle
37996 PUSH EAX
37997 CALL ShowWindow
37998 @@exit:
37999 end;
38000 {$ELSE ASM_VERSION} //Pascal
38001 procedure TControl.SetWindowState( Value: TWindowState );
38002 begin
38003 if fWindowState <> Value then
38004 begin
38005 fWindowState := Value;
38006 ShowWindow(GetWindowHandle, WindowStateShowCommands[Value]);
38007 end;
38008 end;
38009 {$ENDIF ASM_VERSION}
38011 {$IFDEF ASM_VERSION}
38012 //[procedure TControl.Show]
38013 procedure TControl.Show;
38015 PUSH EBX
38016 MOV EBX, EAX
38017 CALL CreateWindow
38018 MOV DL, 1
38019 MOV EAX, EBX
38020 CALL SetVisible
38021 PUSH [EBX].fHandle
38022 CALL SetForegroundWindow
38023 XCHG EAX, EBX
38024 CALL DoSetFocus
38025 POP EBX
38026 end;
38027 {$ELSE ASM_VERSION} //Pascal
38028 procedure TControl.Show;
38029 begin
38030 CreateWindow;
38031 SetVisible( True );
38032 SetForegroundWindow( Handle );
38033 DoSetFocus;
38034 end;
38035 {$ENDIF ASM_VERSION}
38037 //[procedure TControl.Hide]
38038 procedure TControl.Hide;
38039 begin
38040 SetVisible( False );
38041 end;
38043 {$IFDEF ASM_VERSION}
38044 //[function TControl.Client2Screen]
38045 function TControl.Client2Screen( const P: TPoint ): TPoint;
38047 PUSH ESI
38048 PUSH EDI
38050 MOV ESI, EDX
38051 MOV EDI, ECX
38053 MOVSD
38054 MOVSD
38056 PUSH ECX
38057 MOV ECX, [EAX].fHandle
38058 JECXZ @@exit
38060 PUSH ECX
38061 CALL ClientToScreen
38062 PUSH ECX
38064 @@exit: POP ECX
38065 POP EDI
38066 POP ESI
38067 end;
38068 {$ELSE ASM_VERSION} //Pascal
38069 function TControl.Client2Screen( const P: TPoint ): TPoint;
38070 begin
38071 Result := P;
38072 if fHandle <> 0 then
38073 Windows.ClientToScreen( fHandle, Result );
38074 end;
38075 {$ENDIF ASM_VERSION}
38077 {$IFDEF ASM_VERSION}
38078 //[function TControl.Screen2Client]
38079 function TControl.Screen2Client( const P: TPoint ): TPoint;
38081 PUSH ESI
38082 PUSH EDI
38084 MOV ESI, EDX
38085 MOV EDI, ECX
38087 MOVSD
38088 MOVSD
38090 PUSH ECX
38091 MOV ECX, [EAX].fHandle
38092 JECXZ @@exit
38094 PUSH ECX
38095 CALL ScreenToClient
38096 PUSH ECX
38098 @@exit: POP ECX
38099 POP EDI
38100 POP ESI
38101 end;
38102 {$ELSE ASM_VERSION} //Pascal
38103 function TControl.Screen2Client( const P: TPoint ): TPoint;
38104 begin
38105 Result := P;
38106 if Handle <> 0 then
38107 Windows.ScreenToClient( Handle, Result );
38108 end;
38109 {$ENDIF ASM_VERSION}
38111 {$IFDEF ASM_VERSION}
38112 //[function TControl.ClientRect]
38113 function TControl.ClientRect: TRect;
38115 PUSH [EAX].fClientLeft
38116 PUSH [EAX].fClientRight
38117 PUSH [EAX].fClientTop
38118 PUSH [EAX].fClientBottom
38119 PUSH EDX
38120 PUSH EDX // prepare 'dest' for GetClientRect
38122 PUSH EAX
38123 LEA EAX, [EAX].fBoundsRect
38125 XOR ECX, ECX
38126 MOV CL, size_TRect
38128 CALL System.Move
38129 POP EAX // EAX = @Self
38131 CALL TControl.GetWindowHandle
38133 // this version is more correct ?:
38134 //------------------------------
38135 {PUSH EAX
38136 CALL CallTControlCreateWindow
38137 POP EAX
38138 MOV EAX, [EAX].fHandle}
38139 //-------------------------------
38141 TEST EAX, EAX
38142 JZ @@exit
38144 PUSH EAX // prepare 'handle' for GetClientRect
38145 CALL GetClientRect
38146 PUSH EAX
38148 @@exit: POP EDX
38149 POP EDX // EDX = @Result
38150 POP EAX // EAX = fClientBottom
38151 SUB [EDX].TRect.Bottom, EAX
38152 POP EAX // EAX = fClientTop
38153 ADD [EDX].TRect.Top, EAX // Correct Result.Top
38154 POP EAX // EAX = fClientRight
38155 SUB [EDX].TRect.Right, EAX
38156 POP EAX // EAX = fClientLeft
38157 ADD [EDX].TRect.Left, EAX
38158 end;
38159 {$ELSE ASM_VERSION} //Pascal
38160 function TControl.ClientRect: TRect;
38161 const BorderParams: array[ 0..5 ] of DWORD =
38162 ( SM_CXBORDER, SM_CXFRAME, SM_CXSIZEFRAME, SM_CYBORDER, SM_CYFRAME, SM_CYSIZEFRAME );
38163 begin
38164 Result := fBoundsRect;
38165 GetWindowHandle;
38166 //CreateWindow; //virtual!!!
38167 if (fHandle <> 0) then
38168 GetClientRect( fHandle, Result );
38169 Inc( Result.Top, fClientTop );
38170 Dec( Result.Bottom, fClientBottom );
38171 Inc( Result.Left, fClientLeft );
38172 Dec( Result.Right, fClientRight );
38173 end;
38174 {$ENDIF ASM_VERSION}
38176 {$IFDEF ASM_VERSION}
38177 //[procedure TControl.Invalidate]
38178 procedure TControl.Invalidate;
38180 XOR EDX, EDX
38181 CMP [AppletTerminated], DL
38182 JNZ @@exit
38183 MOV ECX, [EAX].fHandle
38184 JECXZ @@exit
38185 PUSH EAX
38186 PUSH 1
38187 PUSH EDX //=0
38188 PUSH ECX
38189 CALL Windows.InvalidateRect
38190 POP EAX
38191 CALL dword ptr[Global_Invalidate]
38192 @@exit:
38193 end;
38194 {$ELSE ASM_VERSION} //Pascal
38195 procedure TControl.Invalidate;
38196 begin
38197 if AppletTerminated then Exit;
38198 if fHandle = 0 then Exit;
38199 InvalidateRect( fHandle, nil, True );
38201 Global_Invalidate( @Self );
38202 end;
38203 {$ENDIF ASM_VERSION}
38205 {$IFDEF ASM_VERSION}
38206 //[function TControl.GetIcon]
38207 function TControl.GetIcon: HIcon;
38209 PUSH EBX
38210 XCHG EBX, EAX
38211 MOV EAX, [EBX].fIcon
38212 INC EAX
38213 JZ @@exit
38214 DEC EAX
38215 JNZ @@exit
38217 MOV ECX, [Applet]
38218 JECXZ @@load
38219 CMP ECX, EBX
38220 JZ @@load
38222 XCHG EAX, ECX
38223 CALL TControl.GetIcon
38224 TEST EAX, EAX
38225 JZ @@exit
38227 XOR EDX, EDX
38228 PUSH EDX
38229 PUSH EDX
38230 PUSH EDX
38231 INC EDX // IMAGE_ICON = 1
38232 PUSH EDX
38233 PUSH EAX
38234 CALL CopyImage
38235 JMP @@store_fIcon
38237 @@main_icon:
38238 DB 'MAINICON',0
38240 @@load:
38241 PUSH offset @@main_icon
38242 PUSH [hInstance]
38243 CALL LoadIcon
38244 @@store_fIcon:
38245 MOV [EBX].fIcon, EAX
38246 @@exit:
38247 POP EBX
38248 end;
38249 {$ELSE ASM_VERSION} //Pascal
38250 function TControl.GetIcon: HIcon;
38251 begin
38252 Result := fIcon;
38253 if Result = THandle( -1 ) then
38254 begin
38255 Result := 0;
38256 Exit;
38257 end;
38258 if Result = 0 then
38259 if (Assigned( Applet )) and
38260 (@Self <> Applet) then
38261 begin
38262 Result := Applet.Icon;
38263 if Result <> 0 then
38264 Result := CopyImage( Result, IMAGE_ICON, 0, 0, 0 );
38266 else
38267 begin
38268 //if Result = 0 then
38269 Result := LoadIcon( hInstance, 'MAINICON' );
38270 //Result := LoadImage( hInstance, 'MAINICON', IMAGE_ICON, 16, 16, LR_SHARED );
38271 end;
38272 fIcon := Result;
38273 end;
38274 {$ENDIF ASM_VERSION}
38277 //[procedure TControl.IconLoad]
38278 procedure TControl.IconLoad(Inst: Integer; ResName: PChar);
38279 begin
38280 Icon := LoadIcon( Inst, ResName );
38281 fIconShared := TRUE;
38282 end;
38284 //[procedure TControl.IconLoadCursor]
38285 procedure TControl.IconLoadCursor(Inst: Integer; ResName: PChar);
38286 begin
38287 Icon := LoadCursor( Inst, ResName );
38288 fIconShared := TRUE;
38289 end;
38291 {$IFDEF ASM_VERSION}
38292 //[function TControl.CallDefWndProc]
38293 function TControl.CallDefWndProc(var Msg: TMsg): Integer;
38295 PUSH [EDX].TMsg.lParam
38296 PUSH [EDX].TMsg.wParam
38297 PUSH [EDX].TMsg.message
38299 MOV ECX, [EAX].fDefWndProc
38300 JECXZ @@defwindowproc
38302 PUSH [EAX].fHandle
38303 PUSH ECX
38304 CALL CallWindowProc
38307 @@defwindowproc:
38308 PUSH [EDX].TMsg.hwnd
38309 CALL DefWindowProc
38310 end;
38311 {$ELSE ASM_VERSION} //Pascal
38312 function TControl.CallDefWndProc(var Msg: TMsg): Integer;
38313 begin
38314 if FDefWndProc <> nil then
38315 Result := CallWindowProc( FDefWndProc, FHandle, Msg.message, Msg.wParam, Msg.lParam )
38316 else
38317 Result := DefWindowProc( Msg.hwnd, Msg.message, Msg.wParam, Msg.lParam );
38318 end;
38319 {$ENDIF ASM_VERSION}
38321 {$IFDEF ASM_VERSION}
38322 //[function TControl.GetWindowState]
38323 function TControl.GetWindowState: TWindowState;
38324 asm //cmd //opd
38325 PUSH EBX
38326 PUSH ESI
38327 XCHG ESI, EAX
38328 MOVZX EBX, [ESI].TControl.fWindowState
38329 MOV ECX, [ESI].TControl.fHandle
38330 JECXZ @@ret_EBX
38331 MOV BL, 2
38332 MOV ESI, ECX
38333 PUSH ESI
38334 CALL IsZoomed
38335 TEST EAX, EAX
38336 JNZ @@ret_EBX
38337 DEC EBX
38338 PUSH ESI
38339 CALL IsIconic
38340 TEST EAX, EAX
38341 JNZ @@ret_EBX
38342 DEC EBX
38343 @@ret_EBX:
38344 XCHG EAX, EBX
38345 POP ESI
38346 POP EBX
38347 end;
38348 {$ELSE ASM_VERSION} //Pascal
38349 function TControl.GetWindowState: TWindowState;
38350 begin
38351 Result := fWindowState;
38352 if Handle <> 0 then
38353 begin
38354 if IsIconic( Handle ) then
38355 Result := wsMinimized
38356 else
38357 if IsZoomed( Handle ) then
38358 Result := wsMaximized
38359 else
38360 Result := wsNormal;
38361 fWindowState := Result;
38362 end;
38363 end;
38364 {$ENDIF ASM_VERSION}
38366 {$IFDEF ASM_VERSION}
38367 //[function TControl.DoSetFocus]
38368 function TControl.DoSetFocus: Boolean;
38370 PUSH ESI
38371 MOV ESI, EAX
38373 {MOV EDX, [ESI].fStyle
38374 TEST EDX, WS_TABSTOP
38375 JZ @@exit}
38377 CALL GetEnabled
38378 TEST AL, AL
38379 JZ @@exit
38381 XOR EAX, EAX
38382 CMP [ESI].fTabstop, AL
38383 JZ @@exit
38385 INC [ESI].TControl.fClickDisabled
38387 PUSH [ESI].fHandle
38388 CALL SetFocus
38390 DEC [ESI].TControl.fClickDisabled
38392 MOV AL, 1
38394 @@exit:
38395 POP ESI
38396 end;
38397 {$ELSE ASM_VERSION} //Pascal
38398 function TControl.DoSetFocus: Boolean;
38399 begin
38400 Result := False;
38401 if Enabled and fTabstop {and (fStyle and WS_TABSTOP <> 0)} then
38402 begin
38403 Inc( fClickDisabled );
38404 SetFocus( fHandle );
38405 Dec( fClickDisabled );
38406 Result := True;
38407 end;
38408 end;
38409 {$ENDIF ASM_VERSION}
38411 //[function TControl.HandleAllocated]
38412 function TControl.HandleAllocated: Boolean;
38413 begin
38414 Result := FHandle <> 0;
38415 end;
38417 {$IFDEF ASM_VERSION}
38418 //[function TControl.GetEnabled]
38419 function TControl.GetEnabled: Boolean;
38421 MOV ECX, [EAX].fHandle
38422 JECXZ @@get_field
38424 PUSH ECX
38425 CALL IsWindowEnabled
38426 { but 00000001 is returned anywhere...
38427 NEG EAX
38428 SBB EAX, EAX
38429 NEG EAX
38433 @@get_field:
38434 TEST byte ptr [EAX].fStyle + 3, 8 //WS_DISABLED shr 3
38435 SETZ AL
38436 end;
38437 {$ELSE ASM_VERSION} //Pascal
38438 function TControl.GetEnabled: Boolean;
38439 begin
38440 if FHandle = 0 then
38441 Result := (Style and WS_DISABLED) = 0
38442 else
38443 Result := IsWindowEnabled( FHandle );
38444 end;
38445 {$ENDIF ASM_VERSION}
38447 {$IFDEF ASM_VERSION}
38448 //[function TControl.IsMainWindow]
38449 function TControl.IsMainWindow: Boolean;
38451 CMP [EAX].fIsControl, 0
38452 JNZ @@no_notmain
38454 XCHG EDX, EAX
38455 MOV EAX, [EDX].fParent
38457 TEST EAX, EAX
38458 JZ @@1
38460 MOV ECX, [EAX].fParent
38461 INC ECX
38462 LOOP @@no_notmain
38464 MOV EAX, [EAX].fChildren
38466 MOV ECX, [EAX].TList.fCount
38467 JECXZ @@no_notmain
38469 MOV EAX, [EAX].TList.fItems
38470 CMP EDX, [EAX]
38471 MOV AL, 1
38472 JMP @@2
38473 @@1:
38474 INC EAX
38475 MOVZX ECX, [AppButtonUsed]
38476 JECXZ @@yes_main
38477 CMP EDX, [Applet]
38478 @@2:
38479 JZ @@yes_main
38481 @@no_notmain:
38482 XOR EAX, EAX
38483 @@yes_main:
38484 end;
38485 {$ELSE ASM_VERSION} //Pascal
38486 function TControl.IsMainWindow: Boolean;
38487 var A: PControl;
38488 begin
38489 Result := False;
38490 if fIsControl then Exit;
38491 A := fParent; // WindowedParent;
38492 if A = nil then
38493 begin
38494 Result := (@Self = Applet) or not AppButtonUsed;
38495 Exit;
38497 else
38498 if A.fParent <> nil then Exit;
38499 //--------------------------------------------------------------------------------
38500 if A.fChildren.fCount = 0 then Exit; // by ECM, fixes AV when user changed (logoff)
38501 //--------------------------------------------------------------------------------
38502 Result := A.fChildren.fItems[ 0 ] = @Self;
38503 end;
38504 {$ENDIF ASM_VERSION}
38506 {$IFDEF ASM_VERSION}
38507 //[function TControl.get_ClassName]
38508 function TControl.get_ClassName: String;
38510 PUSH EBX
38511 XCHG EBX, EAX
38512 XCHG EAX, EDX
38513 MOV EDX, [EBX].fControlClassName
38514 PUSH EAX
38515 CALL System.@LStrFromPChar
38516 POP EAX
38517 CMP [EBX].fCtlClsNameChg, 0
38518 JNZ @@exit
38519 MOV ECX, [EAX]
38520 MOV EDX, offset[ @@obj ]
38521 CALL System.@LStrCat3
38522 JMP @@exit
38524 DD -1, 4
38525 @@obj: DB 'obj_', 0
38527 @@exit:
38528 POP EBX
38529 end;
38530 {$ELSE ASM_VERSION} //Pascal
38531 function TControl.get_ClassName: String;
38532 begin
38533 if not fCtlClsNameChg then
38534 Result := 'obj_' + fControlClassName
38535 else
38536 Result := fControlClassName;
38537 end;
38538 {$ENDIF ASM_VERSION}
38540 //[procedure TControl.set_ClassName]
38541 procedure TControl.set_ClassName(const Value: String);
38542 begin
38543 if fCtlClsNameChg then
38544 FreeMem( fControlClassName );
38545 GetMem( fControlClassName, Length( Value ) + 1 );
38546 StrCopy( fControlClassName, @ Value[ 1 ] );
38547 fCtlClsNameChg := TRUE;
38548 end;
38550 //[function WndProcQueryEndSession]
38551 function WndProcQueryEndSession( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
38552 var Accept: Boolean;
38553 begin
38554 Result := FALSE;
38555 if Msg.message = WM_QUERYENDSESSION then
38556 begin
38557 if Assigned( Sender.fOnQueryEndSession ) then
38558 begin
38559 Accept := TRUE;
38560 Sender.fCloseQueryReason := qShutdown;
38561 if LongBool(Msg.lParam and {ENDSESSION_LOGOFF} DWORD($80000000)) then
38562 Sender.fCloseQueryReason := qLogoff;
38563 Sender.fOnQueryEndSession( Sender, Accept );
38564 Sender.fCloseQueryReason := qClose;
38565 Rslt := Integer( Accept );
38566 // Äîáàâèòü. Íóæíî äëÿ òîãî, ÷òîáû îòìåíèëîñü çàâåðøåíèå ñåàíñà,
38567 // åñëè Accept óñòàíîâëåí â False è ñåàíñ çàâåðøèëñÿ ïðè Accept = True
38568 // Add (YS). To cancel ending session if Accept=FALSE but allow ending
38569 // session if Accept=TRUE.
38570 Result := True; // {YS}: no further processing
38571 end;
38572 end;
38573 end;
38575 //[procedure TControl.SetOnQueryEndSession]
38576 procedure TControl.SetOnQueryEndSession(const Value: TOnEventAccept);
38577 begin
38578 AttachProc( WndProcQueryEndSession );
38579 fOnQueryEndSession := Value;
38580 end;
38582 //[function WndProcMinMaxRestore]
38583 function WndProcMinMaxRestore( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
38584 begin
38585 Result := FALSE;
38586 if Msg.message = WM_SYSCOMMAND then
38587 begin
38588 case Msg.wParam of
38589 SC_MINIMIZE: if Assigned( Sender.fOnMinimize ) then
38590 Sender.fOnMinimize( Sender );
38591 SC_MAXIMIZE: if Assigned( Sender.fOnMaximize ) then
38592 Sender.fOnMaximize( Sender );
38593 SC_RESTORE: if Assigned( Sender.fOnRestore ) then
38594 Sender.fOnRestore( Sender );
38595 end;
38596 end;
38597 end;
38599 //[procedure TControl.SetOnMinMaxRestore]
38600 procedure TControl.SetOnMinMaxRestore(const Index: Integer;
38601 const Value: TOnEvent);
38602 type POnEvent = ^TOnEvent;
38603 {$IFDEF F_P}
38604 var Ptr1: Pointer;
38605 {$ELSE DELPHI}
38606 var Ev: POnEvent;
38607 {$ENDIF F_P/DELPHI}
38608 begin
38609 AttachProc( WndProcMinMaxRestore );
38610 {$IFDEF F_P}
38611 Ptr1 := Self;
38613 MOV EAX, [Ptr1]
38614 LEA EAX, [EAX].TControl.fOnMinimize
38615 ADD EAX, [Index]
38616 MOV EDX, [Value]
38617 MOV [EAX], EDX
38618 MOV EDX, [Value+4]
38619 MOV [EAX+4], EDX
38620 end [ 'EAX', 'EDX' ];
38621 {$ELSE DELPHI}
38622 Ev := Pointer( Integer( @ TMethod( fOnMinimize ).Code ) + Index );
38623 //Ev := Pointer( Integer( @ fOnMinimize ) + Index );
38624 Ev^ := Value;
38625 {$ENDIF}
38626 end;
38628 {$IFDEF F_P}
38629 //[function TControl.GetOnMinMaxRestore]
38630 function TControl.GetOnMinMaxRestore(const Index: Integer): TOnEvent;
38631 begin
38632 CASE Index OF
38633 0: Result := fOnMinimize;
38634 8: Result := fOnMaximize;
38635 16: Result := fOnRestore;
38636 END;
38637 end;
38638 {$ENDIF F_P}
38640 {$IFDEF INPACKAGE}
38641 {$IFDEF ASM_LOCAL}
38642 {$UNDEF ASM_LOCAL}
38643 {$ENDIF}
38644 {$ELSE}
38645 {$IFDEF ASM_VERSION}
38646 {$DEFINE ASM_LOCAL}
38647 {$ENDIF}
38648 {$ENDIF}
38650 {$IFDEF ASM_LOCAL}
38651 //[procedure TControl.SetParent]
38652 procedure TControl.SetParent( Value: PControl );
38654 PUSH EBX
38655 PUSH EDI
38656 XCHG EBX, EAX
38657 MOV EDI, [EBX].fParent
38659 CMP EDX, EDI
38660 JZ @@exit
38662 PUSH EDX
38663 TEST EDI, EDI
38664 JZ @@set_another_parent
38666 MOV EAX, [EDI].fChildren
38667 MOV EDX, EBX
38668 CALL TList.Remove
38670 MOV ECX, [EDI].fNotifyChild
38671 JECXZ @@set_another_parent
38673 MOV EAX, EDI
38674 XOR EDX, EDX
38675 CALL ECX
38677 @@set_another_parent:
38678 POP EDI
38679 MOV [EBX].fParent, EDI
38680 TEST EDI, EDI
38681 JZ @@exit
38683 MOV EAX, [EDI].fChildren
38684 MOV EDX, EBX
38685 CALL TList.Add
38687 {$IFNDEF INPACKAGE}
38688 MOV ECX, [EBX].FHandle
38689 JECXZ @@parentwnd_assigned
38690 PUSH ECX
38691 MOV EAX, EDI
38692 CALL GetWindowHandle
38693 POP ECX
38694 PUSH EAX
38695 PUSH ECX
38696 CALL Windows.SetParent
38698 @@parentwnd_assigned:
38699 {$ENDIF}
38701 MOV ECX, [EDI].fNotifyChild
38702 JECXZ @@exit
38704 MOV EAX, EDI
38705 MOV EDX, EBX
38706 CALL ECX
38708 @@exit:
38709 POP EDI
38710 POP EBX
38711 end;
38712 {$ELSE ASM_VERSION} //Pascal
38713 procedure TControl.SetParent( Value: PControl );
38714 begin
38715 if Value = fParent then Exit;
38716 if fParent <> nil then
38717 begin
38718 fParent.fChildren.Remove( @Self );
38719 if Assigned( fParent.fNotifyChild ) then
38720 fParent.fNotifyChild( fParent, nil );
38721 end;
38722 fParent := Value;
38723 if fParent <> nil then
38724 begin
38725 fParent.fChildren.Add( @Self );
38726 {$IFNDEF INPACKAGE}
38727 if FHandle <> 0 then
38728 Windows.SetParent( FHandle, Value.GetWindowHandle );
38729 {$ENDIF}
38730 if Assigned( fParent.fNotifyChild ) then
38731 fParent.fNotifyChild( fParent, @ Self );
38732 end;
38733 end;
38734 {$ENDIF ASM_VERSION}
38736 //[function TControl.ChildIndex]
38737 function TControl.ChildIndex(Child: PControl): Integer;
38738 begin
38739 Result := fChildren.IndexOf( Child );
38740 end;
38743 //[procedure TControl.MoveChild]
38744 procedure TControl.MoveChild(Child: PControl; NewIdx: Integer);
38745 var I: Integer;
38746 begin
38747 I := ChildIndex( Child );
38748 Assert( I>=0, 'TControl.MoveChild: index out of bounds' );
38749 fChildren.MoveItem( I, NewIdx );
38750 end;
38752 //[procedure TControl.EnableChildren]
38753 procedure TControl.EnableChildren(Enable, Recursive: Boolean);
38754 var I: Integer;
38755 C: PControl;
38756 begin
38757 for I := 0 to ChildCount-1 do
38758 begin
38759 C := Children[ I ];
38760 C.Enabled := Enable;
38761 if Recursive then
38762 C.EnableChildren( Enable, TRUE );
38763 end;
38764 end;
38766 {$IFDEF ASM_VERSION}
38767 //[constructor TControl.CreateParented]
38768 constructor TControl.CreateParented(AParent: PControl);
38769 asm //cmd //opd
38770 //CALL System.@ObjSetup // generated automatically
38771 //JZ @@exit // generated automatically
38772 PUSH EAX
38773 MOV EDX, ECX
38774 MOV ECX, [EAX]
38775 CALL dword ptr [ECX+8]
38776 POP EAX
38777 @@exit:
38778 end;
38779 {$ELSE ASM_VERSION} //Pascal
38780 constructor TControl.CreateParented(AParent: PControl);
38781 begin
38782 InitParented( AParent );
38783 end;
38784 {$ENDIF ASM_VERSION}
38786 {$IFDEF ASM_VERSION}
38787 //[function TControl.GetLeft]
38788 function TControl.GetLeft: Integer;
38790 CALL HelpGetBoundsRect
38791 POP EAX
38793 POP ECX
38794 POP ECX
38795 POP ECX
38796 end;
38797 {$ELSE ASM_VERSION} //Pascal
38798 function TControl.GetLeft: Integer;
38799 begin
38800 Result := BoundsRect.Left;
38801 end;
38802 {$ENDIF ASM_VERSION}
38804 {$IFDEF ASM_VERSION}
38805 //[procedure TControl.SetLeft]
38806 procedure TControl.SetLeft( Value: Integer );
38808 PUSH EDI
38810 PUSH EDX
38811 CALL HelpGetBoundsRect
38812 POP EDX // EDX = Left
38813 POP ECX // ECX = Top
38814 POP EDI // EDI = Right
38816 SUB EDI, EDX // EDI = width
38817 MOV EDX, [ESP+4] // EDX = Left'
38818 ADD EDI, EDX // EDI = Right'
38820 PUSH EDI
38821 PUSH ECX
38822 PUSH EDX
38823 MOV EDX, ESP
38825 CALL SetBoundsRect
38826 ADD ESP, size_TRect + 4
38828 POP EDI
38830 end;
38831 {$ELSE ASM_VERSION} //Pascal
38832 procedure TControl.SetLeft( Value: Integer );
38833 var R: TRect;
38834 begin
38835 R := BoundsRect;
38836 R.Left := Value;
38837 R.Right := Value + Width;
38838 SetBoundsRect( R );
38839 end;
38840 {$ENDIF ASM_VERSION}
38842 {$IFDEF ASM_VERSION}
38843 //[function TControl.GetTop]
38844 function TControl.GetTop: Integer;
38846 CALL HelpGetBoundsRect
38847 POP EDX
38848 POP EAX
38849 POP EDX
38850 POP EDX
38851 end;
38852 {$ELSE ASM_VERSION} //Pascal
38853 function TControl.GetTop: Integer;
38854 begin
38855 Result := BoundsRect.Top;
38856 end;
38857 {$ENDIF ASM_VERSION}
38859 {$IFDEF ASM_VERSION}
38860 //[procedure TControl.SetTop]
38861 procedure TControl.SetTop( Value: Integer );
38863 PUSH ESI
38864 PUSH EDI
38866 PUSH EDX
38867 CALL HelpGetBoundsRect
38868 POP EDX // EDX = Left
38869 POP ECX // ECX = Top
38870 POP EDI // EDI = Right
38871 POP ESI // ESI = Bottom
38873 SUB ESI, ECX // ESI = Height'
38874 POP ECX // ECX = Top'
38875 ADD ESI, ECX // ESI = Bottom'
38877 PUSH ESI
38878 PUSH EDI
38879 PUSH ECX
38880 PUSH EDX
38881 MOV EDX, ESP
38883 CALL SetBoundsRect
38884 ADD ESP, size_TRect
38886 POP EDI
38887 POP ESI
38888 end;
38889 {$ELSE ASM_VERSION} //Pascal
38890 procedure TControl.SetTop( Value: Integer );
38891 var R: TRect;
38892 begin
38893 R := BoundsRect;
38894 R.Top := Value;
38895 R.Bottom := Value + Height;
38896 SetBoundsRect( R );
38897 end;
38898 {$ENDIF ASM_VERSION}
38900 {$IFDEF ASM_VERSION}
38901 //[function TControl.GetWidth]
38902 function TControl.GetWidth: Integer;
38904 CALL HelpGetBoundsRect
38905 POP EDX
38906 POP ECX
38907 POP EAX
38908 SUB EAX, EDX
38909 POP ECX
38910 end;
38911 {$ELSE ASM_VERSION} //Pascal
38912 function TControl.GetWidth: Integer;
38913 begin
38914 with BoundsRect do
38915 Result := Right - Left;
38916 end;
38917 {$ENDIF ASM_VERSION}
38919 {$IFDEF ASM_VERSION}
38920 //[procedure TControl.SetWidth]
38921 procedure TControl.SetWidth( Value: Integer );
38923 PUSH EDX
38925 CALL HelpGetBoundsRect
38926 POP EDX
38927 PUSH EDX
38928 ADD EDX, [ESP].size_TRect
38929 MOV [ESP].TRect.Right, EDX
38931 MOV EDX, ESP
38932 CALL SetBoundsRect
38934 ADD ESP, size_TRect + 4
38935 end;
38936 {$ELSE ASM_VERSION} //Pascal
38937 procedure TControl.SetWidth( Value: Integer );
38938 var R: TRect;
38939 begin
38940 R := BoundsRect;
38941 with R do
38942 Right := Left + Value;
38943 SetBoundsRect( R );
38944 end;
38945 {$ENDIF ASM_VERSION}
38947 {$IFDEF ASM_VERSION}
38948 //[function TControl.GetHeight]
38949 function TControl.GetHeight: Integer;
38951 CALL HelpGetBoundsRect
38952 POP ECX
38953 POP EDX // EDX = top
38954 POP ECX
38955 POP EAX // EAX = bottom
38956 SUB EAX, EDX // result = height
38957 end;
38958 {$ELSE ASM_VERSION} //Pascal
38959 function TControl.GetHeight: Integer;
38960 begin
38961 with BoundsRect do
38962 Result := Bottom - Top;
38963 end;
38964 {$ENDIF ASM_VERSION}
38966 {$IFDEF ASM_VERSION}
38967 //[procedure TControl.SetHeight]
38968 procedure TControl.SetHeight( Value: Integer );
38970 PUSH EDX
38972 CALL HelpGetBoundsRect
38973 MOV EDX, [ESP].TRect.Top
38974 ADD EDX, [ESP].size_TRect
38975 MOV [ESP].TRect.Bottom, EDX
38977 MOV EDX, ESP
38978 CALL SetBoundsRect
38980 ADD ESP, size_TRect + 4
38981 end;
38982 {$ELSE ASM_VERSION} //Pascal
38983 procedure TControl.SetHeight( Value: Integer );
38984 var R: TRect;
38985 begin
38986 R := BoundsRect;
38987 with R do
38988 Bottom := Top + Value;
38989 SetBoundsRect( R );
38990 end;
38991 {$ENDIF ASM_VERSION}
38993 {$IFDEF ASM_VERSION}
38994 //[function TControl.GetPosition]
38995 function TControl.GetPosition: TPoint;
38997 PUSH EDX
38998 CALL HelpGetBoundsRect
38999 POP EAX // EAX = left
39000 POP ECX // ECX = top
39001 POP EDX
39002 POP EDX
39003 POP EDX // EDX = @Result
39004 MOV [EDX], EAX
39005 MOV [EDX+4], ECX
39006 end;
39007 {$ELSE ASM_VERSION} //Pascal
39008 function TControl.GetPosition: TPoint;
39009 begin
39010 Result.x := BoundsRect.Left;
39011 Result.y := BoundsRect.Top;
39012 end;
39013 {$ENDIF ASM_VERSION}
39015 {$IFDEF ASM_VERSION}
39016 //[procedure TControl.Set_Position]
39017 procedure TControl.Set_Position( Value: TPoint );
39019 PUSH ESI
39020 PUSH EDI
39022 PUSH EAX
39023 PUSH EDX
39024 CALL HelpGetBoundsRect
39025 POP EDX // left
39026 POP EAX // top
39027 POP ECX // right
39028 SUB ECX, EDX // ECX = width
39029 POP EDX // bottom
39030 SUB EDX, EAX // EDX = height
39031 POP EAX // EAX = @Value
39032 POP ESI // ESI = @Self
39034 MOV EDI, [EAX+4] // top'
39035 ADD EDX, EDI
39036 PUSH EDX // bottom'
39038 MOV EAX, [EAX] // left'
39039 ADD ECX, EAX
39040 PUSH ECX // right'
39042 PUSH EDI // top'
39043 PUSH EAX // left'
39045 MOV EAX, ESI
39046 MOV EDX, ESP
39047 CALL SetBoundsRect
39049 ADD ESP, size_TRect
39051 POP EDI
39052 POP ESI
39053 end;
39054 {$ELSE ASM_VERSION} //Pascal
39055 procedure TControl.Set_Position( Value: TPoint );
39056 var R: TRect;
39057 begin
39058 R.Top := Value.y;
39059 R.Left := Value.x;
39060 R.Right := R.Left + Width;
39061 R.Bottom := R.Top + Height;
39062 BoundsRect := R;
39063 end;
39064 {$ENDIF ASM_VERSION}
39066 //[function WndProcConstraints]
39067 function WndProcConstraints( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
39068 var MMI: PMinMaxInfo;
39069 begin
39070 Result := FALSE;
39071 if Msg.message = WM_GETMINMAXINFO then
39072 begin
39073 Rslt := Sender.CallDefWndProc( Msg );
39074 MMI := Pointer( Msg.lParam );
39075 if Sender.FMaxWidth > 0 then
39076 begin
39077 MMI.ptMaxSize.x := Sender.FMaxWidth;
39078 MMI.ptMaxTrackSize.x := Sender.FMaxWidth;
39079 end;
39080 if Sender.FMaxHeight > 0 then
39081 begin
39082 MMI.ptMaxSize.y := Sender.FMaxHeight;
39083 MMI.ptMaxTrackSize.y := Sender.FMaxHeight;
39084 end;
39085 MMI.ptMinTrackSize := MakePoint( Sender.FMinWidth, Sender.FMinHeight );
39086 Rslt := 0;
39087 Result := TRUE;
39088 end;
39089 end;
39091 {$IFDEF USE_MHTOOLTIP}
39092 {$DEFINE implementation}
39093 {$I KOLMHToolTip}
39094 {$UNDEF implementation}
39095 {$ENDIF}
39097 //[procedure TControl.SetConstraint]
39098 procedure TControl.SetConstraint(const Index, Value: Integer);
39099 begin
39100 AttachProc( WndProcConstraints );
39101 case Index of
39102 0: FMinWidth := Value;
39103 1: FMinHeight := Value;
39104 2: FMaxWidth := Value;
39105 3: FMaxHeight := Value;
39106 end;
39107 end;
39109 {$IFDEF F_P}
39110 //[function TControl.GetConstraint]
39111 function TControl.GetConstraint(const Index: Integer): Integer;
39112 begin
39113 CASE Index OF
39114 0: Result := FMinWidth;
39115 1: Result := FMinHeight;
39116 2: Result := FMaxWidth;
39117 3: Result := FMaxHeight;
39118 END;
39119 end;
39120 {$ENDIF F_P}
39123 //[function TControl.ControlRect]
39124 function TControl.ControlRect: TRect;
39125 var C: PControl;
39126 R: TRect;
39127 begin
39128 Result := BoundsRect;
39129 C := Parent;
39130 if C <> nil then
39131 begin
39132 //DoScrollOffset( @Result );
39134 if not C.fIsControl then Exit;
39136 R := C.ControlRect;
39137 OffsetRect( Result, R.Left, R.Top );
39139 if C.fChildren <> nil then
39140 if C.FChildren.IndexOf( @Self ) >= C.MembersCount then
39141 begin
39142 R := C.ClientRect;
39143 Dec( R.Top, C.fClientTop );
39144 Dec( R.Left, C.fClientLeft );
39145 OffsetRect( Result, R.Left, R.Top );
39146 end;
39147 end;
39148 end;
39151 //[function TControl.ControlAtPos]
39152 function TControl.ControlAtPos( X, Y: Integer;
39153 IgnoreDisabled: Boolean ): PControl;
39154 var I: Integer;
39155 C: PControl;
39156 CR, VR: TRect;
39157 begin
39158 Result := nil;
39159 CR := ControlRect;
39160 if Windowed then
39161 CR := MakeRect( 0, 0, 0, 0 );
39162 X := X + CR.Left; // - R.Left;
39163 Y := Y + CR.Top; // - R.Top;
39164 for I := ChildCount { + MembersCount } - 1 downto 0 do
39165 begin
39166 C := Children[ I ]; //Members[ I ];
39167 if C.Visible then
39168 if (not IgnoreDisabled) or IgnoreDisabled and C.Enabled then
39169 begin
39170 VR := C.ControlRect;
39171 if (X >= VR.Left) and (X < VR.Right) and
39172 (Y >= VR.Top) and (Y < VR.Bottom) then
39173 begin
39174 Result := C;
39175 Exit;
39176 end;
39177 end;
39178 end;
39179 end;
39181 //[PROCEDURE DefaultPaintBackground]
39182 {$IFDEF ASM_VERSION}
39183 procedure DefaultPaintBackground( Sender: PControl; DC: HDC; Rect: PRect );
39185 PUSH EDI
39187 PUSH EDI
39188 MOV EDI, ESP
39190 PUSH ECX
39191 PUSH EDX
39193 MOV EAX, [EAX].TControl.fColor
39194 CALL Color2RGB
39195 PUSH EAX
39196 CALL CreateSolidBrush
39197 STOSD
39198 MOV EDI, EAX
39199 CALL windows.FillRect
39200 PUSH EDI
39201 CALL DeleteObject
39202 POP EDI
39203 end;
39204 {$ELSE ASM_VERSION} //Pascal
39205 procedure DefaultPaintBackground( Sender: PControl; DC: HDC; Rect: PRect );
39206 var B: HBrush;
39207 begin
39208 B := CreateSolidBrush( Color2Rgb( Sender.Color ) );
39209 Windows.FillRect( DC, Rect^, B );
39210 DeleteObject( B );
39211 end;
39212 {$ENDIF ASM_VERSION}
39213 //[END DefaultPaintBackground]
39215 //[procedure TControl.PaintBackground]
39216 procedure TControl.PaintBackground( DC: HDC; Rect: PRect );
39217 begin
39218 Global_OnPaintBkgnd( @Self, DC, Rect );
39219 end;
39221 //[procedure TControl.SetCtlColor]
39222 {$IFDEF ASM_VERSION}
39223 procedure TControl.SetCtlColor( Value: TColor );
39225 PUSH EBX
39226 MOV EBX, EAX
39228 {$IFNDEF INPACKAGE}
39229 PUSH EDX
39231 CALL GetWindowHandle
39232 XCHG ECX, EAX
39234 POP EDX
39235 {$ELSE}
39236 MOV ECX, [EBX].fHandle
39237 {$ENDIF}
39239 JECXZ @@1
39241 MOVZX ECX, [EBX].fCommandActions.aSetBkColor
39242 JECXZ @@1
39244 PUSH EDX
39246 XCHG EAX, EDX
39247 PUSH ECX
39248 CALL Color2RGB
39249 POP ECX
39251 PUSH EAX // Color2RGB( Value )
39252 PUSH 0 // 0
39253 PUSH ECX // fCommandActions.aSetBkColor
39254 PUSH EBX // @ Self
39255 CALL TControl.Perform
39257 POP EDX
39259 @@1:
39260 CMP EDX, [EBX].fColor
39261 JZ @@exit
39263 MOV [EBX].fColor, EDX
39265 XOR ECX, ECX
39266 XCHG ECX, [EBX].fTmpBrush
39267 JECXZ @@setbrushcolor
39269 PUSH EDX
39270 PUSH ECX
39271 CALL DeleteObject
39272 POP EDX
39274 @@setbrushcolor:
39275 MOV ECX, [EBX].fBrush
39276 JECXZ @@invldte
39278 XCHG EAX, ECX
39279 MOV ECX, EDX
39280 //MOV EDX, go_Color
39281 XOR EDX, EDX
39282 CALL TGraphicTool.SetInt
39284 @@invldte:
39285 XCHG EAX, EBX
39286 CALL TControl.Invalidate
39287 @@exit:
39288 POP EBX
39289 end;
39290 {$ELSE ASM_VERSION} //Pascal
39291 procedure TControl.SetCtlColor( Value: TColor );
39292 begin
39293 {$IFNDEF INPACKAGE}
39294 if GetWindowHandle <> 0 then
39295 {$ELSE}
39296 if fHandle <> 0 then
39297 {$ENDIF}
39298 if fCommandActions.aSetBkColor <> 0 then
39299 Perform( fCommandActions.aSetBkColor, 0, Color2RGB( Value ) );
39300 if fColor = Value then Exit;
39301 fColor := Value;
39302 if fTmpBrush <> 0 then
39303 begin
39304 DeleteObject( fTmpBrush );
39305 fTmpBrush := 0;
39306 end;
39307 if fBrush <> nil then
39308 fBrush.Color := Value;
39309 Invalidate;
39310 end;
39311 {$ENDIF ASM_VERSION}
39313 {$IFDEF ASM_VERSION}
39314 //[function TControl.GetParentWnd]
39315 function TControl.GetParentWnd( NeedHandle: Boolean ): HWnd;
39317 MOV ECX, [EAX].fParent
39318 JECXZ @@exit
39320 PUSH ECX
39321 TEST DL, DL
39322 JZ @@load_handle
39324 XCHG EAX, ECX
39325 CALL GetWindowHandle
39327 @@load_handle:
39328 POP ECX
39329 MOV ECX, [ECX].fHandle
39331 @@exit: XCHG EAX, ECX
39333 end;
39334 {$ELSE ASM_VERSION} //Pascal
39335 function TControl.GetParentWnd( NeedHandle: Boolean ): HWnd;
39336 var C: PControl;
39337 begin
39338 Result := 0;
39339 C := fParent; // WindowedParent;
39340 if C <> nil then
39341 begin
39342 if NeedHandle then
39343 C.GetWindowHandle;
39344 Result := C.fHandle;
39345 end;
39346 end;
39347 {$ENDIF ASM_VERSION}
39349 {$IFDEF ASM_VERSION}
39350 //[procedure TControl.CreateChildWindows]
39351 procedure TControl.CreateChildWindows;
39353 PUSH ESI
39354 MOV ESI, [EAX].TControl.fChildren
39355 MOV ECX, [ESI].TList.fCount
39356 MOV ESI, [ESI].TList.fItems
39357 JECXZ @@exit
39359 @@loop: PUSH ECX
39360 LODSD
39361 CALL CallTControlCreateWindow
39362 //CALL TControl.GetWindowHandle
39363 POP ECX
39364 LOOP @@loop
39366 @@exit: POP ESI
39367 end;
39368 {$ELSE ASM_VERSION} //Pascal
39369 procedure TControl.CreateChildWindows;
39370 var I: Integer;
39371 C: PControl;
39372 begin
39373 for I := 0 to fChildren.Count - 1 do
39374 begin
39375 C := fChildren.fItems[ I ];
39376 //C.GetWindowHandle;
39377 C.CreateWindow; //virtual!!!
39378 end;
39379 end;
39380 {$ENDIF ASM_VERSION}
39382 //[function TControl.GetMembers]
39383 function TControl.GetMembers(Idx: Integer): PControl;
39384 begin
39385 Result := fChildren.fItems[ Idx ];
39386 end;
39388 {$IFDEF ASM_VERSION}
39389 //[procedure TControl.DestroyChildren]
39390 procedure TControl.DestroyChildren;
39392 PUSH ESI
39394 MOV EAX, [EAX].fChildren
39395 PUSH EAX
39396 MOV ECX, [EAX].TList.fCount
39397 JECXZ @@clear
39398 MOV ESI, [EAX].TList.fItems
39399 LEA ESI, [ESI + ECX*4 - 4] // is order really important ?
39401 @@loop: STD //
39402 LODSD
39403 CLD //
39405 PUSH ECX
39406 CALL TObj.Free
39407 POP ECX
39409 LOOP @@loop
39411 @@clear:
39412 POP EAX
39413 CALL TList.Clear
39415 POP ESI
39416 end;
39417 {$ELSE ASM_VERSION} //Pascal
39418 procedure TControl.DestroyChildren;
39419 var I: Integer;
39420 W: PControl;
39421 begin
39422 for I := fChildren.fCount - 1 downto 0 do
39423 begin
39424 W := fChildren.fItems[ I ];
39425 W.Free;
39426 end;
39427 fChildren.Clear;
39428 end;
39429 {$ENDIF ASM_VERSION}
39431 {//-
39432 //[function TControl.WindowedParent]
39433 function TControl.WindowedParent: PControl;
39434 begin
39435 Result := fParent;
39436 end;}
39438 {$IFDEF ASM_VERSION}
39439 //[function TControl.ProcessMessage]
39440 function TControl.ProcessMessage: Boolean;
39441 const size_TMsg = sizeof( TMsg );
39443 PUSH EBX
39444 XCHG EBX, EAX
39446 ADD ESP, -size_TMsg-4
39448 MOV EDX, ESP
39449 PUSH 1
39450 XOR ECX, ECX
39451 PUSH ECX
39452 PUSH ECX
39453 PUSH ECX
39454 PUSH EDX
39455 CALL PeekMessage
39457 TEST EAX, EAX
39458 JZ @@exit
39460 MOV EDX, [ESP].TMsg.message
39461 CMP DX, WM_QUIT
39462 JNZ @@tran_disp
39463 MOV [AppletTerminated], 1
39464 JMP @@fin
39466 @@tran_disp:
39467 MOV ECX, [EBX].fExMsgProc
39468 JECXZ @@do_tran_disp
39469 MOV EAX, EBX
39470 MOV EDX, ESP
39471 CALL ECX
39472 TEST AL, AL
39473 JNZ @@fin
39475 @@do_tran_disp:
39476 MOV EAX, ESP
39477 PUSH EAX
39478 PUSH EAX
39479 CALL TranslateMessage
39480 CALL DispatchMessage
39482 @@fin:
39483 MOV AX, word ptr [ESP].TMsg.message
39484 TEST AX, AX
39485 SETNZ AL
39487 @@exit: ADD ESP, size_TMsg+4
39488 POP EBX
39489 end;
39490 {$ELSE ASM_VERSION} //Pascal
39491 function TControl.ProcessMessage: Boolean;
39492 var Msg: TMsg;
39493 begin
39494 Result := False;
39495 if PeekMessage( Msg, 0, 0, 0, PM_REMOVE ) then
39496 begin
39497 Result := Msg.message <> 0;
39498 if (Msg.message = WM_QUIT) then
39499 AppletTerminated := True
39500 else
39501 begin
39502 if not(Assigned( fExMsgProc ) and fExMsgProc( @Self, Msg )) then
39503 begin
39504 TranslateMessage( Msg );
39505 DispatchMessage( Msg );
39506 end;
39507 end;
39508 end;
39509 end;
39510 {$ENDIF ASM_VERSION}
39512 {$IFDEF ASM_VERSION}
39513 //[procedure TControl.ProcessMessages]
39514 procedure TControl.ProcessMessages;
39516 @@loo: PUSH EAX
39517 CALL ProcessMessage
39518 DEC AL
39519 POP EAX
39520 JZ @@loo
39521 end;
39522 {$ELSE ASM_VERSION} //Pascal
39523 procedure TControl.ProcessMessages;
39524 begin
39525 while ProcessMessage do ;
39526 end;
39527 {$ENDIF ASM_VERSION}
39529 //[procedure TControl.ProcessMessagesEx]
39530 procedure TControl.ProcessMessagesEx;
39531 begin
39532 PostMessage( GetWindowHandle, CM_PROCESS, 0, 0 );
39533 ProcessMessages;
39534 end;
39536 //[FUNCTION WndProcForm]
39537 {$IFDEF ASM_VERSION}
39538 function WndProcForm(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
39539 const szPaintStruct = sizeof(TPaintStruct);
39540 asm //cmd //opd
39541 CMP word ptr [EDX].TMsg.message, WM_ENDSESSION
39542 JNE @@chk_WM_SETFOCUS
39544 CMP [EDX].TMsg.wParam, 0
39545 JZ @@ret_false
39547 CALL TObj.RefDec
39548 XOR EAX, EAX
39549 MOV [AppletRunning], AL
39550 XCHG EAX, [Applet]
39551 INC [AppletTerminated]
39553 CALL TObj.Free
39554 CALL System.@Halt0
39555 //-------
39557 @@chk_WM_SETFOCUS:
39558 CMP word ptr [EDX].TMsg.message, WM_SETFOCUS
39559 JNE @@ret_false
39561 PUSH EBX
39562 PUSH ESI
39563 XOR EBX, EBX
39564 XCHG ESI, EAX
39565 {$IFDEF FIX_MODAL_SETFOCUS}
39566 MOV ECX, [ESI].TControl.fModalForm
39567 JECXZ @@no_fix_modal_setfocus
39568 PUSH [ECX].TControl.fHandle
39569 CALL SetFocus
39570 @@no_fix_modal_setfocus:
39571 {$ENDIF}
39573 MOV ECX, [ESI].TControl.FCurrentControl
39574 JECXZ @@1
39575 INC EBX
39576 XCHG EAX, ECX
39578 // or CreateForm?
39579 PUSH EAX
39580 CALL CallTControlCreateWindow
39581 POP EAX
39582 PUSH [EAX].TControl.fHandle
39584 CALL SetFocus
39585 @@1: MOV ECX, [Applet]
39586 JECXZ @@ret_EBX
39587 CMP ECX, ESI
39588 JE @@ret_EBX
39589 MOV [ECX].TControl.FCurrentControl, ESI
39590 @@ret_EBX:
39591 XCHG EAX, EBX
39592 POP ESI
39593 POP EBX
39596 @@ret_false:
39597 XOR EAX, EAX
39598 end;
39599 {$ELSE ASM_VERSION} //Pascal
39600 function WndProcForm(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
39601 var App: PControl;
39602 begin
39603 Result := True;
39604 with Self_{-}^{+} do
39605 case Msg.message of
39606 WM_ENDSESSION:
39607 begin
39608 if Msg.wParam <> 0 then
39609 begin
39610 Self_.RefDec;
39611 { Normally, WM_ENDSESSION is sent to a main form, not to Applet.
39612 Since we do not plan further working after handling this message,
39613 we decrease RefCount for the form (in was increased in EnumDynHandlers
39614 to prevent object destroying while its message processing is not
39615 finished). }
39616 App := Applet;
39617 //Rslt := 0; { We will not return any result at all. }
39618 {$IFDEF DEBUG_ENDSESSION}
39619 EndSession_Initiated := TRUE;
39620 LogFileOutput( GetStartDir + 'es_debug.txt',
39621 'Self_=' + Int2Hex( DWORD( Self_ ), 8 ) +
39622 ' Self_.Handle=' + Int2Str( Self_.FHandle ) );
39623 {$ENDIF}
39624 AppletTerminated := TRUE;
39625 AppletRunning := FALSE;
39626 Applet := nil;
39627 App.Free; { We provide OnDestroy handlers to be called for any objects here }
39628 Halt; { Stop further executing. }
39629 end else Result := FALSE;
39630 end;
39631 WM_SETFOCUS:
39632 begin
39633 {$IFDEF NEW_MODAL}
39634 if fModalForm <> nil then
39635 SetFocus( fModalForm.fHandle )
39636 else if ( FCurrentControl <> nil ) and not ( fCurrentControl.IsForm xor fIsApplet ) then
39637 {$ELSE not NEW_MODAL}
39638 if FCurrentControl <> nil then
39639 {$ENDIF}
39640 begin
39641 FCurrentControl.CreateWindow; //virtual!!!
39642 SetFocus( FCurrentControl.fHandle );
39644 else
39645 Result := False;
39646 if assigned( Applet ) and (Applet <> Self_) then
39647 Applet.FCurrentControl := Self_;
39648 end;
39649 else Result := False;
39650 end;
39651 end;
39652 {$ENDIF ASM_VERSION}
39653 //[END WndProcForm]
39655 //[FUNCTION GetPrevCtrlBoundsRect]
39656 {$IFDEF ASM_VERSION}
39657 function GetPrevCtrlBoundsRect( P: PControl; var R: TRect ): Boolean;
39659 MOV EDX, EBX
39660 MOV EAX, [EBX].TControl.fParent
39661 TEST EAX, EAX
39662 JZ @@exit
39663 PUSH EAX
39664 CALL TControl.ChildIndex
39665 TEST EAX, EAX
39666 XCHG EDX, EAX
39667 POP EAX
39668 JZ @@exit
39669 DEC EDX
39670 CALL TControl.GetMembers
39672 POP ECX // retaddr
39673 ADD ESP, -size_TRect
39674 MOV EDX, ESP
39675 PUSH ECX
39676 CALL TControl.GetBoundsRect
39677 STC // return CARRY
39678 @@exit:
39679 end;
39680 {$ELSE ASM_VERSION} //Pascal
39681 function GetPrevCtrlBoundsRect( P: PControl; var R: TRect ): Boolean;
39682 var Idx: Integer;
39683 begin
39684 Result := False;
39685 if P.FParent = nil then Exit;
39686 Idx := P.FParent.ChildIndex( P ) - 1;
39687 if Idx < 0 then Exit;
39688 Result := True;
39689 R := P.FParent.Children[ Idx ].BoundsRect;
39690 end;
39691 {$ENDIF ASM_VERSION}
39692 //[END GetPrevCtrlBoundsRect]
39694 {$IFDEF ASM_VERSION}
39695 //[function TControl.PlaceUnder]
39696 function TControl.PlaceUnder: PControl;
39698 PUSH EBX
39699 XCHG EBX, EAX
39700 CALL GetPrevCtrlBoundsRect
39701 JNC @@exit
39702 POP EDX // EDX = Left
39703 MOV EAX, EBX
39704 CALL TControl.SetLeft
39706 POP EDX
39707 POP EDX
39708 POP EDX // EDX = Bottom
39710 MOV EAX, [EBX].fParent
39711 ADD EDX, [EAX].fMargin
39713 MOV EAX, EBX
39714 CALL TControl.SetTop
39715 @@exit:
39716 XCHG EAX, EBX
39717 POP EBX
39718 end;
39719 {$ELSE ASM_VERSION} //Pascal
39720 function TControl.PlaceUnder: PControl;
39721 var R: TRect;
39722 begin
39723 Result := @Self;
39724 if not GetPrevCtrlBoundsRect( @Self, R ) then Exit;
39725 Top := R.Bottom + fParent.fMargin;
39726 Left := R.Left;
39727 end;
39728 {$ENDIF ASM_VERSION}
39730 {$IFDEF ASM_VERSION}
39731 //[function TControl.PlaceDown]
39732 function TControl.PlaceDown: PControl;
39734 PUSH EBX
39735 XCHG EBX, EAX
39736 CALL GetPrevCtrlBoundsRect
39737 JNC @@exit
39738 POP EDX
39739 POP EDX
39740 POP EDX
39741 POP EDX // EDX = Bottom
39743 MOV EAX, [EBX].fParent
39744 ADD EDX, [EAX].fMargin
39746 MOV EAX, EBX
39747 CALL TControl.SetTop
39748 @@exit:
39749 XCHG EAX, EBX
39750 POP EBX
39751 end;
39752 {$ELSE ASM_VERSION} //Pascal
39753 function TControl.PlaceDown: PControl;
39754 var R: TRect;
39755 begin
39756 Result := @Self;
39757 if not GetPrevCtrlBoundsRect( @Self, R ) then Exit;
39758 Top := R.Bottom + fParent.fMargin;
39759 end;
39760 {$ENDIF ASM_VERSION}
39762 {$IFDEF ASM_VERSION}
39763 //[function TControl.PlaceRight]
39764 function TControl.PlaceRight: PControl;
39766 PUSH EBX
39767 XCHG EBX, EAX
39768 CALL GetPrevCtrlBoundsRect
39769 JNC @@exit
39770 POP EDX
39771 POP EDX // EDX = Top
39772 MOV EAX, EBX
39773 CALL TControl.SetTop
39774 POP EDX // EDX = Right
39776 MOV EAX, [EBX].fParent
39777 ADD EDX, [EAX].fMargin
39779 POP ECX
39780 MOV EAX, EBX
39781 CALL TControl.SetLeft
39782 @@exit:
39783 XCHG EAX, EBX
39784 POP EBX
39785 end;
39786 {$ELSE ASM_VERSION} //Pascal
39787 function TControl.PlaceRight: PControl;
39788 var R: TRect;
39789 begin
39790 Result := @Self;
39791 if not GetPrevCtrlBoundsRect( @Self, R ) then Exit;
39792 Top := R.Top;
39793 Left := R.Right + fParent.fMargin;
39794 end;
39795 {$ENDIF ASM_VERSION}
39797 {$IFDEF ASM_VERSION}
39798 //[function TControl.SetSize]
39799 function TControl.SetSize(W, H: Integer): PControl;
39801 PUSH EBX
39802 XCHG EBX, EAX
39803 SUB ESP, 16
39804 XCHG EAX, EDX
39805 MOV EDX, ESP
39806 PUSH ECX // save H
39807 PUSH EAX // save W
39808 MOV EAX, EBX
39809 CALL GetBoundsRect
39810 POP ECX // pop W
39811 JECXZ @@nochg_W
39812 ADD ECX, [ESP+4].TRect.Left
39813 MOV [ESP+4].TRect.Right, ECX
39814 @@nochg_W:
39815 POP ECX // pop H
39816 JECXZ @@nochg_H
39817 ADD ECX, [ESP].TRect.Top
39818 MOV [ESP].TRect.Bottom, ECX
39819 @@nochg_H:
39820 MOV EAX, EBX
39821 MOV EDX, ESP
39822 CALL TControl.SetBoundsRect
39823 ADD ESP, 16
39824 XCHG EAX, EBX
39825 POP EBX
39826 end;
39827 {$ELSE ASM_VERSION} //Pascal
39828 function TControl.SetSize(W, H: Integer): PControl;
39829 var R: TRect;
39830 begin
39831 R := BoundsRect;
39832 if W > 0 then R.Right := R.Left + W;
39833 if H > 0 then R.Bottom := R.Top + H;
39834 SetBoundsRect( R );
39835 Result := @Self;
39836 end;
39837 {$ENDIF ASM_VERSION}
39839 //[function TControl.SetClientSize]
39840 function TControl.SetClientSize(W, H: Integer): PControl;
39841 begin
39842 if W > 0 then ClientWidth := W;
39843 if H > 0 then ClientHeight := H;
39844 Result := @Self;
39845 end;
39847 {$IFDEF ASM_VERSION}
39848 //[function TControl.AlignLeft]
39849 function TControl.AlignLeft(P: PControl): PControl;
39851 PUSH EAX
39852 MOV EAX, EDX
39853 CALL TControl.GetLeft
39854 MOV EDX, EAX
39855 POP EAX
39856 PUSH EAX
39857 CALL TControl.SetLeft
39858 POP EAX
39859 end;
39860 {$ELSE ASM_VERSION} //Pascal
39861 function TControl.AlignLeft(P: PControl): PControl;
39862 begin
39863 Result := @Self;
39864 Left := P.Left;
39865 end;
39866 {$ENDIF ASM_VERSION}
39868 {$IFDEF ASM_VERSION}
39869 //[function TControl.AlignTop]
39870 function TControl.AlignTop(P: PControl): PControl;
39872 PUSH EAX
39873 MOV EAX, EDX
39874 CALL TControl.GetTop
39875 MOV EDX, EAX
39876 POP EAX
39877 PUSH EAX
39878 CALL TControl.SetTop
39879 POP EAX
39880 end;
39881 {$ELSE ASM_VERSION} //Pascal
39882 function TControl.AlignTop(P: PControl): PControl;
39883 begin
39884 Result := @Self;
39885 Top := P.Top;
39886 end;
39887 {$ENDIF ASM_VERSION}
39889 //[FUNCTION WndProcCtrl]
39890 {$IFDEF ASM_VERSION} // see addition for combobox in pas version
39891 function WndProcCtrl( Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
39892 asm //cmd //opd
39893 PUSH EBX
39894 XCHG EBX, EAX
39895 PUSH ESI
39896 PUSH EDI
39897 MOV EDI, EDX
39898 MOV EDX, [EDI].TMsg.message
39900 SUB DX, CN_CTLCOLORMSGBOX
39901 CMP DX, CN_CTLCOLORSTATIC-CN_CTLCOLORMSGBOX
39902 JA @@chk_CM_COMMAND
39903 @@2:
39904 PUSH ECX
39905 MOV EAX, [EBX].TControl.fTextColor
39906 CALL Color2RGB
39907 XCHG ESI, EAX
39908 PUSH ESI
39909 PUSH [EDI].TMsg.wParam
39910 CALL SetTextColor
39911 CMP [EBX].TControl.fTransparent, 0
39912 JZ @@opaque
39914 PUSH Windows.TRANSPARENT
39915 PUSH [EDI].TMsg.wParam
39916 CALL SetBkMode
39917 PUSH NULL_BRUSH
39918 CALL GetStockObject
39919 JMP @@ret_rslt
39921 @@opaque:
39922 MOV EAX, [EBX].TControl.fColor
39923 CALL Color2RGB
39924 XCHG ESI, EAX
39925 PUSH OPAQUE
39926 PUSH [EDI].TMsg.wParam
39927 CALL SetBkMode
39928 PUSH ESI
39929 PUSH [EDI].TMsg.wParam
39930 CALL SetBkColor
39932 MOV EAX, EBX
39933 CALL Global_GetCtlBrushHandle
39934 @@ret_rslt:
39935 XCHG ECX, EAX
39936 @@tmpbrushready:
39937 POP EAX
39938 MOV [EAX], ECX
39939 @@ret_true:
39940 MOV AL, 1
39942 JMP @@ret_EAX
39944 @@chk_CM_COMMAND:
39945 CMP word ptr [EDI].TMsg.message, CM_COMMAND
39946 JNE @@chk_WM_SETFOCUS
39948 PUSH ECX
39950 MOVZX ECX, word ptr [EDI].TMsg.wParam+2
39951 CMP CX, [EBX].TControl.fCommandActions.aClick
39952 JNE @@chk_aEnter
39954 CMP [EBX].TControl.fClickDisabled, 0
39955 JG @@calldef
39956 MOV EAX, EBX
39957 CALL TControl.DoClick
39958 JMP @@calldef
39960 @@chk_aEnter:
39961 LEA EAX, [EBX].TControl.fOnEnter
39962 CMP CX, [EBX].TControl.fCommandActions.aEnter
39963 JE @@goEvent
39964 LEA EAX, [EBX].TControl.fOnLeave
39965 CMP CX, [EBX].TControl.fCommandActions.aLeave
39966 JE @@goEvent
39967 LEA EAX, [EBX].TControl.fOnChange
39968 CMP CX, [EBX].TControl.fCommandActions.aChange
39969 JNE @@chk_aSelChange
39970 @@goEvent:
39971 MOV ECX, [EAX].TMethod.Code
39972 JECXZ @@2calldef
39973 MOV EAX, [EAX].TMethod.Data
39974 MOV EDX, EBX
39975 CALL ECX
39976 @@2calldef:
39977 JMP @@calldef
39979 @@chk_aSelChange:
39980 CMP CX, [EBX].TControl.fCommandActions.aSelChange
39981 JNE @@chk_WM_SETFOCUS_1
39982 MOV EAX, EBX
39983 CALL TControl.DoSelChange
39985 @@calldef:
39986 XCHG EAX, EBX
39987 MOV EDX, EDI
39988 CALL TControl.CallDefWndProc
39989 JMP @@ret_rslt
39991 @@chk_WM_SETFOCUS_1:
39992 POP ECX
39993 @@chk_WM_SETFOCUS:
39994 XOR EAX, EAX
39995 CMP word ptr [EDI].TMsg.message, WM_SETFOCUS
39996 JNE @@ret_EAX
39998 MOV [ECX], EAX
39999 MOV EAX, EBX
40000 CALL TControl.ParentForm
40001 TEST EAX, EAX
40002 JZ @@ret_true
40004 MOV [EAX].TControl.FCurrentControl, EBX
40005 XOR EAX, EAX
40007 PUSH EDX
40008 @@2ret_EAX:
40009 POP EDX
40011 @@ret_EAX:
40012 POP EDI
40013 POP ESI
40014 POP EBX
40015 end;
40016 {$ELSE ASM_VERSION} //Pascal
40017 function WndProcCtrl(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
40018 var F: PControl;
40019 Cmd : DWORD;
40020 begin
40021 //Result := FALSE;
40022 with Self_{-}^{+} do
40023 case Msg.message of
40024 CN_CTLCOLORMSGBOX..CN_CTLCOLORSTATIC:
40025 begin
40026 SetTextColor(Msg.WParam, Color2RGB(fTextColor));
40027 if fTransparent {AND (fPaintDC = Msg.wParam)} then
40028 begin
40029 SetBkMode( Msg.wParam, Windows.TRANSPARENT );
40030 Rslt := GetStockObject( NULL_BRUSH );
40032 else
40033 begin
40034 SetBkMode( Msg.wParam, Windows.OPAQUE );
40035 SetBkColor(Msg.WParam, Color2RGB( fColor ) );
40036 Rslt := Global_GetCtlBrushHandle( Self_ );
40037 end;
40038 Result := TRUE;
40039 end;
40040 CM_COMMAND:
40041 begin
40042 Result := True;
40043 Cmd := HiWord( Msg.wParam );
40044 if Cmd = fCommandActions.aClick then
40045 begin
40046 if Integer( fClickDisabled ) <= 0 then
40047 DoClick;
40048 end else
40049 if Cmd = fCommandActions.aEnter then
40050 begin
40051 if Assigned( fOnEnter ) then fOnEnter( Self_ );
40052 end else
40053 if Cmd = fCommandActions.aLeave then
40054 begin
40055 if Assigned( fOnLeave ) then fOnLeave( Self_ );
40056 end else
40057 if Integer(Cmd) = fCommandActions.aChange then
40058 begin
40059 if Assigned( fOnChange ) then fOnChange( Self_ );
40060 //if fTransparent then Invalidate;
40061 end else
40062 if Integer(Cmd) = fCommandActions.aSelChange then
40063 begin
40064 DoSelChange;
40065 // if fTransparent then Invalidate;
40067 else Result := False;
40069 if Result then
40070 Rslt := CallDefWndProc( Msg );
40072 end;
40074 WM_SETFOCUS:
40075 begin
40076 Rslt := 0;
40077 Result := TRUE;
40078 F := ParentForm;
40079 if F <> nil then
40080 begin
40081 F.fCurrentControl := Self_;
40082 Result := False; // go further handling
40083 end;
40084 end;
40085 {$IFDEF ESC_CLOSE_DIALOGS}
40086 //---------------------------------Babenko Alexey--------------------------
40087 WM_KEYDOWN:
40088 begin
40089 if (Self_.ParentForm.ExStyle and WS_EX_DLGMODALFRAME) <> 0 then
40090 if Msg.wParam = 27 then SendMessage(Self_.ParentForm.Handle, WM_CLOSE, 0, 0);
40091 result:=false;
40092 end;
40093 //---------------------------------Babenko Alexey--------------------------
40094 {$ENDIF ESC_CLOSE_DIALOGS}
40095 else Result := False;
40096 end;
40097 end;
40098 {$ENDIF ASM_VERSION}
40099 //[END WndProcCtrl]
40101 //[FUNCTION WndProcPaint]
40102 {$IFDEF ASM_noVERSION}
40103 function WndProcPaint( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
40104 const szPaintStruct = sizeof(TPaintStruct);
40105 asm //cmd //opd
40106 CMP word ptr [EDX].TMsg.message, WM_PRINT
40107 JE @@print
40108 CMP word ptr [EDX].TMsg.message, WM_PAINT
40109 JNE @@ret_false
40110 @@print:
40111 CMP word ptr [EAX].TControl.fOnPaint.TMethod.Code+2, 0
40112 JE @@ret_false
40113 PUSH EBX
40114 PUSH ESI
40116 XCHG EBX, EAX
40117 MOV ESI, EDX
40118 XOR EAX, EAX
40119 PUSH ECX
40120 PUSH EAX
40121 PUSH EAX
40122 PUSH EAX
40123 PUSH EAX
40124 CALL CreateRectRgn
40125 MOV [EBX].TControl.fUpdRgn, EAX
40127 MOVSX EDX, [EBX].TControl.fEraseUpdRgn
40128 PUSH EDX
40129 PUSH EAX
40130 PUSH [EBX].TControl.fHandle
40131 CALL GetUpdateRgn
40133 CMP EAX, 1
40134 JA @@collectUpdRgn
40136 XOR EAX, EAX
40137 XCHG EAX, [EBX].TControl.fUpdRgn
40138 PUSH EAX
40139 CALL DeleteObject
40141 @@collectUpdRgn:
40142 MOV ECX, [EBX].TControl.fCollectUpdRgn
40143 JECXZ @@asg_fPaintDC
40144 XCHG EAX, ECX
40145 MOV ECX, [EBX].TControl.fUpdRgn
40146 JECXZ @@asg_fPaintDC
40148 PUSH RGN_OR
40149 PUSH ECX
40150 PUSH EAX
40151 PUSH EAX
40152 CALL CombineRgn
40154 DEC EAX
40155 JNZ @@invalidateRgn
40157 ADD ESP, -16
40158 PUSH ESP
40159 PUSH [EBX].TControl.fHandle
40160 CALL Windows.GetClientRect
40162 PUSH [EBX].TControl.fCollectUpdRgn
40163 CALL DeleteObject
40164 CALL CreateRectRgn
40165 MOV [EBX].TControl.fCollectUpdRgn, EAX
40167 @@invalidateRgn:
40168 MOVSX EDX, [EBX].TControl.fEraseUpdRgn
40169 PUSH EDX
40170 PUSH [EBX].TControl.fCollectUpdRgn
40171 PUSH [EBX].TControl.fHandle
40172 CALL InvalidateRgn
40175 @@asg_fPaintDC:
40176 MOV ECX, [ESI].TMsg.wParam
40177 INC ECX
40178 LOOP @@storePaintDC
40180 ADD ESP, -szPaintStruct
40181 PUSH ESP
40182 PUSH [EBX].TControl.fHandle
40183 CALL BeginPaint
40184 XCHG ECX, EAX
40185 @@storePaintDC:
40186 MOV [EBX].TControl.fPaintDC, ECX
40187 XCHG EAX, ECX
40189 MOV ECX, [EBX].TControl.fCollectUpdRgn
40190 JECXZ @@doOnPaint
40192 PUSH ECX
40193 PUSH EAX
40194 CALL SelectClipRgn
40196 @@doOnPaint:
40197 MOV ECX, [EBX].TControl.fPaintDC
40198 MOV EDX, EBX
40199 MOV EAX, [EBX].TControl.fOnPaint.TMethod.Data
40200 CALL dword ptr [EBX].TControl.fOnPaint.TMethod.Code
40202 MOV ECX, [EBX].TControl.fCanvas
40203 JECXZ @@e_paint
40205 XCHG EAX, ECX
40206 XOR EDX, EDX
40207 CALL TCanvas.SetHandle
40209 @@e_paint:
40210 MOV ECX, [ESI].TMsg.wParam
40211 INC ECX
40212 LOOP @@zero_fPaintDC
40214 PUSH ESP
40215 PUSH [EBX].TControl.fHandle
40216 CALL EndPaint
40217 ADD ESP, szPaintStruct
40219 @@zero_fPaintDC:
40220 XOR ECX, ECX
40221 MOV [EBX].TControl.fPaintDC, ECX
40223 POP EAX
40224 MOV [EAX], ECX
40226 XCHG ECX, [EBX].TControl.fUpdRgn
40227 JECXZ @@exit_True
40229 PUSH ECX
40230 CALL DeleteObject
40232 @@exit_True:
40233 POP ESI
40234 POP EBX
40235 MOV AL, 1
40238 @@ret_false:
40239 XOR EAX, EAX
40240 end;
40241 {$ELSE ASM_VERSION} //Pascal
40242 function WndProcPaint( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
40243 var PaintStruct: TPaintStruct;
40244 CR: TRect;
40245 Cplxity: Integer;
40246 OldPaintDC: HDC;
40247 begin
40248 with Self_{-}^{+} do
40249 case Msg.message of
40250 WM_PRINT,
40251 WM_PAINT: if assigned( fOnPaint ) then
40252 begin
40253 fUpdRgn := CreateRectRgn( 0, 0, 0, 0 );
40254 Cplxity := Integer( GetUpdateRgn( fHandle, fUpdRgn, fEraseUpdRgn ) );
40255 if (Cplxity = NULLREGION) or (Cplxity = ERROR) then
40256 begin
40257 DeleteObject( fUpdRgn );
40258 fUpdRgn := 0;
40259 end;
40261 if (fCollectUpdRgn <> 0) and (fUpdRgn <> 0) then
40262 begin
40263 if CombineRgn( fCollectUpdRgn, fCollectUpdRgn, fUpdRgn, RGN_OR )
40264 = COMPLEXREGION then
40265 begin
40266 windows.GetClientRect( Self_.fHandle, CR );
40267 DeleteObject( fCollectUpdRgn );
40268 fCollectUpdRgn := CreateRectRgnIndirect( CR );
40269 end;
40270 InvalidateRgn( fHandle, fCollectUpdRgn, fEraseUpdRgn );
40271 end;
40273 OldPaintDC := fPaintDC;
40274 fPaintDC := Msg.wParam;
40275 if fPaintDC = 0 then
40276 fPaintDC := BeginPaint( fHandle, PaintStruct );
40278 if fCollectUpdRgn <> 0 then
40279 SelectClipRgn( fPaintDC, fCollectUpdRgn );
40281 fOnPaint( Self_, fPaintDC );
40283 if assigned( Self_.fCanvas ) then
40284 Self_.fCanvas.SetHandle( 0 );
40286 if Msg.wParam = 0 then
40287 EndPaint( fHandle, PaintStruct );
40288 fPaintDC := OldPaintDC;
40290 Rslt := 0;
40292 Result := True;
40293 if fUpdRgn <> 0 then
40294 DeleteObject( fUpdRgn );
40295 fUpdRgn := 0;
40296 Exit;
40297 end;
40298 end;
40299 Result := FALSE;
40300 end;
40301 {$ENDIF ASM_VERSION}
40302 //[END WndProcPaint]
40304 //[procedure TControl.SetOnPaint]
40305 procedure TControl.SetOnPaint( const Value: TOnPaint );
40306 begin
40307 fOnPaint := Value;
40308 AttachProc( WndProcPaint );
40309 end;
40312 //[function WndProcEraseBkgnd]
40313 function WndProcEraseBkgnd( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
40314 var PaintStruct: TPaintStruct;
40315 OldPaintDC: HDC;
40316 begin
40317 Result := FALSE;
40318 if Msg.message = WM_ERASEBKGND then
40319 begin
40320 if Assigned( Sender.OnEraseBkgnd ) then
40321 begin
40322 OldPaintDC := Sender.fPaintDC;
40323 Sender.fPaintDC := Msg.wParam;
40324 if Sender.fPaintDC = 0 then
40325 Sender.fPaintDC := BeginPaint( Sender.fHandle, PaintStruct );
40326 Sender.OnEraseBkgnd( Sender, Msg.wParam );
40327 if Msg.wParam = 0 then
40328 EndPaint( Sender.fHandle, PaintStruct );
40329 if Assigned( Sender.fCanvas ) then
40330 Sender.fCanvas.SetHandle( 0 );
40331 Sender.fPaintDC := OldPaintDC;
40332 Rslt := 0;
40333 Result := TRUE;
40335 else
40336 Rslt := 0;
40337 end;
40338 end;
40340 //[procedure TControl.SetOnEraseBkgnd]
40341 procedure TControl.SetOnEraseBkgnd(const Value: TOnPaint);
40342 begin
40343 fOnEraseBkgnd := Value;
40344 AttachProc( WndProcEraseBkgnd );
40345 end;
40347 //[FUNCTION WndProcGradient]
40348 {$IFDEF ASM_noVERSION}
40349 function WndProcGradient( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
40350 const szPaintStruct = sizeof( TPaintStruct );
40351 asm //cmd //opd
40352 CMP word ptr [EDX].TMsg.message, WM_PRINTCLIENT
40353 JE @@print
40354 CMP word ptr [EDX].TMsg.message, WM_PAINT
40355 JNE @@ret_false
40356 @@print:
40357 PUSHAD
40358 XCHG EDI, EAX
40359 MOV ESI, EDX
40360 XOR EAX, EAX
40361 MOV [ECX], EAX
40362 OR EAX, [ESI].TMsg.wParam
40363 JNZ @@1
40364 ADD ESP, -szPaintStruct
40365 PUSH ESP
40366 PUSH [EDI].TControl.fHandle
40367 CALL BeginPaint
40368 @@1: MOV [EDI].TControl.fPaintDC, EAX
40369 ADD ESP, -16
40370 MOV EDX, ESP
40371 MOV EAX, EDI
40372 CALL TControl.ClientRect
40373 MOV EAX, [EDI].TControl.fColor1
40374 CALL Color2RGB
40375 XCHG EBX, EAX
40376 MOV EAX, [EDI].TControl.fColor2
40377 CALL Color2RGB
40378 MOV EBP, [ESP].TRect.Bottom
40379 @@loo:
40380 MOV EDX, [ESP].TRect.Top
40381 CMP EBP, EDX
40382 JLE @@e_loo
40383 INC EDX
40384 MOV [ESP].TRect.Bottom, EDX
40386 INC EBP
40387 PUSH EAX
40389 PUSH EAX
40390 {SUB AL, BL
40391 MOV AH, 0
40393 CWDE}
40394 AND EAX, $FF
40395 MOV EDX, EBX
40396 AND EDX, $FF
40397 SUB EAX, EDX
40400 MOV ECX, [ESP+8].TRect.Top
40401 IMUL ECX
40402 IDIV EBP
40403 XOR EDX, EDX
40404 ADD AL, BL
40405 MOV AH, 0
40406 CWDE
40407 XCHG [ESP], EAX
40409 PUSH EAX
40410 {SUB AH, BH
40411 MOV AL, AH
40412 MOV AH, 0
40414 CWDE}
40415 SHR EAX, 8
40416 AND EAX, $FF
40417 MOV EDX, EBX
40418 SHR EDX, 8
40419 AND EDX, $FF
40420 SUB EAX, EDX
40422 IMUL ECX
40423 IDIV EBP
40424 ADD AL, BH
40425 AND EAX, $FF
40426 SHL EAX, 8
40427 XCHG [ESP], EAX
40429 SHR EAX, 16
40430 MOV EDX, EBX
40431 SHR EDX, 16
40432 PUSH EDX
40433 SUB EAX, EDX
40434 IMUL ECX
40435 IDIV EBP
40436 POP EDX
40437 //AND EAX, $FF00
40438 ADD EAX, EDX
40439 SHL EAX, 16
40441 POP EDX
40442 MOV AH, DH
40443 POP EDX
40444 MOV AL, DL
40446 PUSH EAX
40447 CALL CreateSolidBrush
40449 PUSH EAX
40451 PUSH EAX
40452 LEA EDX, [ESP+12]
40453 PUSH EDX
40454 PUSH [EDI].TControl.fPaintDC
40455 CALL Windows.FillRect
40457 CALL DeleteObject
40459 POP EAX
40460 DEC EBP
40461 INC [ESP].TRect.Top
40462 JMP @@loo
40463 @@e_loo:
40464 ADD ESP, 16
40465 MOV ECX, [ESI].TMsg.wParam
40466 INC ECX
40467 LOOP @@2
40468 PUSH ESP
40469 PUSH [EDI].TControl.fHandle
40470 CALL EndPaint
40471 ADD ESP, szPaintStruct
40472 @@2: XOR EAX, EAX
40473 MOV [EDI].TControl.fPaintDC, EAX
40474 POPAD
40475 MOV Al, 1
40477 @@ret_false:
40478 XOR EAX, EAX
40479 end;
40480 {$ELSE ASM_VERSION} //Pascal
40481 function WndProcGradient( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
40482 var PaintStruct: TPaintStruct;
40483 Bmp: PBitmap;
40484 CR: TRect;
40485 I: Integer;
40486 R, G, B: Integer;
40487 R1, G1, B1: Integer;
40488 C: TColor;
40489 W, H, WH: Integer;
40490 W9x: Boolean;
40491 Br: HBrush;
40492 //Save: Integer;
40493 OldPaintDC: HDC;
40494 begin
40495 case Msg.message of
40496 WM_PAINT, WM_PRINTCLIENT:
40497 begin
40498 OldPaintDC := Self_.fPaintDC;
40499 Self_.fPaintDC := Msg.wParam;
40500 if Self_.fPaintDC = 0 then
40501 Self_.fPaintDC := BeginPaint( Self_.fHandle, PaintStruct );
40502 CR := Self_.ClientRect;
40503 W9x := WinVer < wvNT;
40504 W := 1;
40505 H := CR.Bottom;
40506 WH := H;
40507 Bmp := nil;
40508 if Self_.fGradientStyle = gsHorizontal then
40509 begin
40510 W := CR.Right;
40511 H := 1;
40512 WH := W;
40513 end;
40514 if not W9x then
40515 Bmp := NewDIBBitmap( W, H, pf32bit );
40516 C := Color2RGB( Self_.fColor1 );
40517 R := C shr 16;
40518 G := (C shr 8) and $FF;
40519 B := C and $FF;
40520 C := Color2RGB( Self_.fColor2 );
40521 R1 := C shr 16;
40522 G1 := (C shr 8) and $FF;
40523 B1 := C and $FF;
40524 for I := 0 to WH-1 do
40525 begin
40526 C := ((( R + (R1 - R) * I div WH ) and $FF) shl 16) or
40527 ((( G + (G1 - G) * I div WH ) and $FF) shl 8) or
40528 ( B + (B1 - B) * I div WH ) and $FF;
40529 if W9x then
40530 begin
40531 if Self_.fGradientStyle = gsVertical then
40532 CR.Bottom := CR.Top + 1
40533 else
40534 CR.Right := CR.Left + 1;
40535 Br := CreateSolidBrush( C );
40536 Windows.FillRect( Self_.fPaintDC, CR, Br );
40537 DeleteObject( Br );
40538 if Self_.fGradientStyle = gsVertical then
40539 Inc( CR.Top )
40540 else
40541 Inc( CR.Left );
40543 else
40544 begin
40545 if Self_.fGradientStyle = gsVertical then
40546 Bmp.DIBPixels[ 0, I ] := C
40547 else
40548 Bmp.DIBPixels[ I, 0 ] := C;
40549 end;
40550 end;
40551 if not W9x then
40552 begin
40553 SetStretchBltMode( Self_.fPaintDC, HALFTONE );
40554 SetBrushOrgEx( Self_.fPaintDC, 0, 0, nil );
40555 StretchBlt( Self_.fPaintDC, 0, 0, CR.Right, CR.Bottom, Bmp.Canvas.Handle,
40556 0, 0, W, H, SRCCOPY );
40557 Bmp.Free;
40558 end;
40559 if Msg.wParam = 0 then
40560 EndPaint( Self_.fHandle, PaintStruct );
40561 Self_.fPaintDC := OldPaintDC;
40562 Rslt := 0;
40563 Result := True;
40564 Exit;
40565 end;
40566 end;
40567 Result := False;
40568 end;
40569 {$ENDIF ASM_VERSION}
40570 //[END WndProcGradient]
40572 //[function WndProcGradientEx]
40573 function WndProcGradientEx( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
40574 function Ceil( X: Double ): Integer;
40575 begin
40576 Result := Round( X ) + 1;
40577 end;
40578 const
40579 SQRT2 = 1.4142135623730950488016887242097;
40581 RC, R0: TRect;
40582 C, C2: TColor;
40583 R1, G1, B1: Integer;
40584 R2, G2, B2: Integer;
40585 DX1, DX2, DY1, DY2, DR, DG, DB, K: Double;
40586 PaintStruct: TPaintStruct;
40587 I: Integer;
40588 Br: HBrush;
40589 Rgn: HRgn;
40590 Poly: array[ 0..3 ] of TPoint;
40591 OldPaintDC: HDC;
40592 fX1, fX2, fY1, fY2: Double;
40594 procedure OffsetF( DX, DY: Double );
40595 begin
40596 fX1 := fX1 + DX;
40597 fX2 := fX2 + DX;
40598 fY1 := fY1 + DY;
40599 fY2 := fY2 + DY;
40600 end;
40601 begin
40602 Result := FALSE;
40603 if (Msg.message <> WM_PAINT) and (Msg.message <> WM_PRINTCLIENT) then Exit;
40604 if Self_.fGradientStyle in [ gsHorizontal, gsVertical ] then
40605 begin
40606 Result := WndProcGradient( Self_, Msg, Rslt );
40607 Exit;
40608 end;
40609 C := Color2RGB( Self_.fColor2 );
40610 R2 := C and $FF;
40611 G2 := (C shr 8) and $FF;
40612 B2 := (C shr 16) and $FF;
40613 C := Color2RGB( Self_.fColor1 );
40614 R1 := C and $FF;
40615 G1 := (C shr 8) and $FF;
40616 B1 := (C shr 16) and $FF;
40617 DR := (R2 - R1) / 256;
40618 DG := (G2 - G1) / 256;
40619 DB := (B2 - B1) / 256;
40620 OldPaintDC := Self_.fPaintDC;
40621 Self_.fPaintDC := Msg.wParam;
40622 if Self_.fPaintDC = 0 then
40623 Self_.fPaintDC := BeginPaint( Self_.fHandle, PaintStruct );
40624 RC := Self_.ClientRect;
40625 fX1 := 0;
40626 fY1 := 0;
40627 case Self_.fGradientStyle of
40628 gsRombic:
40629 //RF := MakeRect( 0, 0, RC.Right div 128, RC.Bottom div 128 );
40630 begin
40631 fX2 := RC.Right / 128;
40632 fY2 := RC.Bottom / 128;
40633 end;
40634 gsElliptic:
40635 //RF := MakeRect( 0, 0, Ceil( RC.Right / 256 * SQRT2 ), Ceil( RC.Bottom / 256 * SQRT2 ) );
40636 begin
40637 fX2 := RC.Right / 256 * SQRT2;
40638 fY2 := RC.Bottom / 256 * SQRT2;
40639 end;
40640 else
40641 //RF := MakeRect( 0, 0, RC.Right div 256, RC.Bottom div 256 );
40642 begin
40643 fX2 := RC.Right / 256;
40644 fY2 := RC.Bottom / 256;
40645 end;
40646 end;
40647 case Self_.fGradientStyle of
40648 gsRectangle, gsRombic, gsElliptic:
40649 begin
40650 case Self_.FGradientLayout of
40651 glCenter, glTop, glBottom:
40652 //OffsetRect( RF, (RC.Right - RF.Right) div 2, 0 );
40653 OffsetF( (RC.Right - fX2) / 2, 0 );
40654 glTopRight, glBottomRight, glRight:
40655 //OffsetRect( RF, RC.Right - RF.Right div 2, 0 );
40656 OffsetF( RC.Right - fX2 / 2, 0 );
40657 glTopLeft, glBottomLeft, glLeft:
40658 //OffsetRect( RF, -RF.Right div 2, 0 );
40659 OffsetF( -fX2 / 2, 0 );
40660 end;
40661 case Self_.FGradientLayout of
40662 glCenter, glLeft, glRight:
40663 //OffsetRect( RF, 0, (RC.Bottom - RF.Bottom) div 2 );
40664 OffsetF( 0, (RC.Bottom - fY2) / 2 );
40665 glBottom, glBottomLeft, glBottomRight:
40666 //OffsetRect( RF, 0, RC.Bottom - RF.Bottom div 2 );
40667 OffsetF( 0, RC.Bottom - fY2 / 2 );
40668 glTop, glTopLeft, glTopRight:
40669 //OffsetRect( RF, 0, -RF.Bottom div 2 );
40670 OffsetF( 0, -fY2 / 2 )
40671 end;
40672 end;
40673 end;
40674 DX1 := -fX1 / 255; //(-RF.Left) / 255;
40675 DY1 := -fY1 / 255; // (-RF.Top) / 255;
40676 DX2 := (RC.Right - fX2) / 255; //(RC.Right - RF.Right) / 255;
40677 DY2 := (RC.Bottom - fY2) / 255;
40678 case Self_.fGradientStyle of
40679 gsRombic, gsElliptic:
40680 begin
40681 if DX2 < -DX1 then DX2 := -DX1;
40682 if DY2 < -DY1 then DY2 := -DY1;
40683 K := 2;
40684 if Self_.fGradientStyle = gsElliptic then K := SQRT2;
40685 DX2 := DX2 * K;
40686 DY2 := DY2 * K;
40687 DX1 := -DX2;
40688 DY1 := -DY2;
40689 end;
40690 end;
40691 C2 := C;
40692 for I := 0 to 255 do
40693 begin
40694 if (I < 255) then
40695 begin
40696 C2 := TColor( (( Ceil( B1 + DB * (I+1) ) and $FF) shl 16) or
40697 (( Ceil( G1 + DG * (I+1) ) and $FF) shl 8) or
40698 Ceil( R1 + DR * (I+1) ) and $FF );
40699 if (Self_.fGradientStyle in [gsRombic,gsElliptic,gsRectangle]) and
40700 (C2 = C) then continue;
40701 end;
40702 Br := CreateSolidBrush( C );
40703 R0 := MakeRect( Ceil( fX1 + DX1 * I ),
40704 Ceil( fY1 + DY1 * I ),
40705 Ceil( fX2 + DX2 * I ) + 1,
40706 Ceil( fY2 + DY2 * I ) + 1 );
40707 Rgn := 0;
40708 case Self_.fGradientStyle of
40709 gsRectangle:
40710 Rgn := CreateRectRgnIndirect( R0 );
40711 gsRombic:
40712 begin
40713 Poly[ 0 ].x := R0.Left;
40714 Poly[ 0 ].y := R0.Top + (R0.Bottom - R0.Top) div 2;
40715 Poly[ 1 ].x := R0.Left + (R0.Right - R0.Left) div 2;
40716 Poly[ 1 ].y := R0.Top;
40717 Poly[ 2 ].x := R0.Right;
40718 Poly[ 2 ].y := Poly[ 0 ].y;
40719 Poly[ 3 ].x := Poly[ 1 ].x;
40720 Poly[ 3 ].y := R0.Bottom;
40721 Rgn := CreatePolygonRgn( Poly[ 0 ].x, 4, ALTERNATE );
40722 end;
40723 gsElliptic:
40724 Rgn := CreateEllipticRgnIndirect( R0 );
40725 end;
40726 if Rgn <> 0 then
40727 begin
40728 if Rgn <> NULLREGION then
40729 begin
40730 Windows.FillRgn( Self_.fPaintDC, Rgn, Br );
40731 ExtSelectClipRgn( Self_.fPaintDC, Rgn, RGN_DIFF );
40732 end;
40733 DeleteObject( Rgn );
40734 end;
40735 DeleteObject( Br );
40736 C := C2;
40737 end;
40738 if Self_.fPaintDC <> HDC( Msg.wParam ) then
40739 EndPaint( Self_.fHandle, PaintStruct );
40740 Self_.fPaintDC := OldPaintDC;
40741 Rslt := 0;
40742 Result := True;
40743 end;
40746 //[function WndProcLabelEffect]
40747 function WndProcLabelEffect( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
40749 Sz: TSize;
40750 P0: TPoint;
40751 CR: TRect;
40752 B : Boolean;
40753 CShadow: TColor;
40754 Target: PCanvas;
40755 Txt: String;
40756 LCaption: PChar;
40757 OldPaintDC: HDC;
40759 procedure doTextOut( shfx, shfy: Integer; col: TColor );
40760 begin
40761 SetTextColor( Target.fHandle, col );
40762 Windows.ExtTextOut( Target.fHandle, P0.x + shfx, P0.y + shfy,
40763 ETO_CLIPPED, @CR,
40764 PChar(Txt), Length(Txt), nil );
40765 //GDIFlush; // for test only
40766 end;
40768 var I, J, Istp : Integer;
40769 PS: TPaintStruct;
40770 //DoEndPaint: Boolean;
40771 begin
40772 Result := False;
40774 case Msg.message of
40776 WM_SETTEXT:
40777 begin
40778 LCaption := PChar( Msg.lParam );
40779 if LCaption <> Self_.fCaption then
40780 begin
40781 if Self_.fCaption <> nil then
40782 FreeMem( Self_.fCaption );
40783 GetMem( Self_.fCaption, StrLen( LCaption ) + 1 );
40784 StrCopy( Self_.fCaption, LCaption );
40785 end;
40786 Result := True;
40787 Rslt := 1;
40788 Exit;
40789 end;
40791 WM_PRINTCLIENT, WM_PAINT:
40792 begin
40793 OldPaintDC := Self_.fPaintDC;
40794 Self_.fPaintDC := Msg.wParam;
40795 if Self_.fPaintDC = 0 then
40796 Self_.fPaintDC := BeginPaint( Self_.fHandle, PS );
40797 begin
40798 Target := Self_.Canvas;
40799 Txt := Self_.fCaption;
40800 Target.TextArea( Txt, Sz, P0 );
40801 if Self_.fShadowDeep <> 0 then
40802 begin
40803 for B := False to Self_.fCtl3D do
40804 begin
40805 Inc( Sz.cx, Abs( Self_.fShadowDeep ) );
40806 Inc( Sz.cy, Abs( Self_.fShadowDeep ) );
40807 end;
40808 end;
40809 CR := Self_.ClientRect;
40810 case Self_.fTextAlign of
40811 taCenter: P0.x := P0.x + (CR.Right - Sz.cx) div 2;
40812 taRight: P0.x := P0.x + (CR.Right - Sz.cx);
40813 end;
40814 case Self_.fVerticalAlign of
40815 vaCenter: P0.y := P0.y + (CR.Bottom - Sz.cy) div 2;
40816 vaBottom: P0.y := P0.y + (CR.Bottom - Sz.cy);
40817 end;
40818 if Self_.fShadowDeep <> 0 then
40819 begin
40820 if Self_.fColor2 = clNone then
40821 CShadow := ColorsMix(Color2RGB(Self_.fTextColor),Color2RGB(Self_.fColor2))
40822 else
40823 CShadow := Color2RGB( Self_.fColor2 );
40824 if not Self_.fTransparent then
40825 Target.FillRect( CR ); // GDIFlush; for test only
40826 //Target.DeselectHandles;
40827 Target.RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
40828 SetBkMode( Target.fHandle, Windows.TRANSPARENT );
40829 if Self_.fCtl3D then
40830 begin
40831 I := - Self_.fShadowDeep;
40832 Istp := 1;
40833 if Self_.ShadowDeep > 0 then Istp := -1;
40834 repeat
40835 J := - Self_.fShadowDeep;
40836 repeat
40837 if not ( (I=0) and (J=0) ) then
40838 begin
40839 if (I * Istp < 0) and (J * Istp < 0) then
40840 begin
40841 doTextOut( I, J, CShadow );
40842 end;
40843 end;
40844 J := J - Istp;
40845 until J = Self_.fShadowDeep - IStp;
40846 I := I - Istp;
40847 until I = Self_.fShadowDeep - IStp;
40849 else
40850 doTextout( Self_.fShadowDeep, Self_.fShadowdeep, CShadow );
40851 doTextout( 0, 0, Color2RGB(Self_.fTextColor) );
40853 else
40854 begin
40855 //Target.DeselectHandles;
40856 Target.RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
40857 SetBkMode( Target.fHandle, Windows.TRANSPARENT );
40858 //Target.TextRect( CR, P0.x, P0.y, Txt );
40859 doTextout( 0, 0, Color2RGB(Self_.fTextColor) );
40860 end;
40861 end;
40862 if assigned( Self_.fCanvas ) then
40863 Self_.fCanvas.SetHandle( 0 );
40864 if MSg.wParam = 0 then
40865 EndPaint( Self_.fHandle, PS );
40866 Self_.fPaintDC := OldPaintDC;
40867 Rslt := 0;
40868 Result := True;
40869 Exit;
40870 end;
40871 end;
40872 end;
40874 {$IFDEF ASM_VERSION}
40875 //[procedure TControl.DoClick]
40876 procedure TControl.DoClick;
40878 PUSH EAX
40879 CALL [EAX].fControlClick
40880 POP EDX
40882 MOV ECX, [EDX].fOnClick.TMethod.Code
40883 JECXZ @@exit
40884 MOV EAX, [EDX].fOnClick.TMethod.Data
40885 CALL ECX
40886 @@exit:
40887 end;
40888 {$ELSE ASM_VERSION} //Pascal
40889 procedure TControl.DoClick;
40890 begin
40891 fControlClick( @Self );
40892 if Assigned( fOnClick ) then
40893 fOnClick( @Self );
40894 end;
40895 {$ENDIF ASM_VERSION}
40897 {$IFDEF ASM_VERSION}
40898 //[function TControl.ParentForm]
40899 function TControl.ParentForm: PControl;
40901 @@1: CMP [EAX].fIsControl, 0
40902 JZ @@exit
40903 MOV EAX, [EAX].fParent
40904 TEST EAX, EAX
40905 JNZ @@1
40906 @@exit:
40907 end;
40908 {$ELSE ASM_VERSION} //Pascal
40909 function TControl.ParentForm: PControl;
40910 begin
40911 Result := @Self;
40912 if Result.fIsControl then
40913 repeat
40914 Result := Result.fParent;
40915 until (Result = nil) or not Result.fIsControl;
40916 end;
40917 {$ENDIF ASM_VERSION}
40919 {$IFDEF ASM_VERSION}
40920 //[procedure TControl.SetProgressColor]
40921 procedure TControl.SetProgressColor(const Value: TColor);
40923 PUSH EDX
40924 PUSH EAX
40925 MOV EAX, EDX
40926 CALL Color2RGB
40927 POP EDX
40928 PUSH EDX
40929 PUSH EAX
40930 PUSH 0
40931 PUSH PBM_SETBARCOLOR
40932 PUSH EDX
40933 CALL Perform
40934 TEST EAX, EAX
40935 POP EAX
40936 POP EDX
40937 JZ @@exit
40938 MOV [EAX].fTextColor, EDX
40939 @@exit:
40940 end;
40941 {$ELSE ASM_VERSION} //Pascal
40942 procedure TControl.SetProgressColor(const Value: TColor);
40943 begin
40944 if Perform( PBM_SETBARCOLOR, 0, Color2RGB(Value) ) <> 0 then
40945 fTextColor := Value;
40946 end;
40947 {$ENDIF ASM_VERSION}
40949 //[procedure TControl.SetShadowDeep]
40950 procedure TControl.SetShadowDeep(const Value: Integer);
40951 begin
40952 fShadowDeep := Value;
40953 Invalidate;
40954 end;
40956 {$IFDEF ASM_VERSION}
40957 //[function TControl.GetFont]
40958 function TControl.GetFont: PGraphicTool;
40960 MOV ECX, [EAX].FFont
40961 INC ECX
40962 LOOP @@exit
40963 PUSH EAX
40964 CALL NewFont
40965 POP EDX
40966 MOV [EDX].FFont, EAX
40967 MOV ECX, [EDX].fTextColor
40968 MOV [EAX].TGraphicTool.fData.Color, ECX
40969 MOV [EAX].TGraphicTool.fOnChange.TMethod.Code, offset[FontChanged]
40970 MOV [EAX].TGraphicTool.fOnChange.TMethod.Data, EDX
40972 @@exit: XCHG EAX, ECX
40973 end;
40974 {$ELSE ASM_VERSION} //Pascal
40975 function TControl.GetFont: PGraphicTool;
40976 begin
40977 if FFont = nil then
40978 begin
40979 FFont := NewFont;
40980 FFont.fData.Color := fTextColor;
40981 FFont.OnChange := FontChanged;
40982 end;
40983 Result := FFont;
40984 end;
40985 {$ENDIF ASM_VERSION}
40987 {$IFDEF ASM_VERSION}
40988 //[function TControl.GetBrush]
40989 function TControl.GetBrush: PGraphicTool;
40991 MOV ECX, [EAX].FBrush
40992 INC ECX
40993 LOOP @@exit
40994 PUSH EAX
40995 CALL NewBrush
40996 POP EDX
40997 MOV [EDX].FBrush, EAX
40998 MOV ECX, [EDX].fColor
40999 MOV [EAX].TGraphicTool.fData.Color, ECX
41000 MOV [EAX].TGraphicTool.fOnChange.TMethod.Code, offset[BrushChanged]
41001 MOV [EAX].TGraphicTool.fOnChange.TMethod.Data, EDX
41003 @@exit: XCHG EAX, ECX
41004 end;
41005 {$ELSE ASM_VERSION} //Pascal
41006 function TControl.GetBrush: PGraphicTool;
41007 begin
41008 if FBrush = nil then
41009 begin
41010 FBrush := NewBrush;
41011 FBrush.fData.Color := fColor;
41012 FBrush.OnChange := BrushChanged;
41013 end;
41014 Result := FBrush;
41015 end;
41016 {$ENDIF ASM_VERSION}
41018 {$IFDEF ASM_VERSION}
41019 //[procedure TControl.FontChanged]
41020 procedure TControl.FontChanged(Sender: PGraphicTool);
41022 MOV ECX, [EDX].TGraphicTool.fData.Color
41023 MOV [EAX].fTextColor, ECX
41024 PUSH EAX
41025 CALL ApplyFont2Wnd
41026 POP EAX
41027 CALL Invalidate
41028 end;
41029 {$ELSE ASM_VERSION} //Pascal
41030 procedure TControl.FontChanged(Sender: PGraphicTool);
41031 begin
41032 fTextColor := Sender.fData.Color;
41033 ApplyFont2Wnd;
41034 Invalidate;
41035 end;
41036 {$ENDIF ASM_VERSION}
41038 {$IFDEF ASM_VERSION}
41039 //[procedure TControl.BrushChanged]
41040 procedure TControl.BrushChanged(Sender: PGraphicTool);
41042 MOV ECX, [EDX].TGraphicTool.fData.Color
41043 MOV [EAX].fColor, ECX
41044 XOR ECX, ECX
41045 XCHG ECX, [EAX].fTmpBrush
41046 JECXZ @@inv
41047 PUSH EAX
41048 PUSH ECX
41049 CALL DeleteObject
41050 POP EAX
41051 @@inv: CALL Invalidate
41052 end;
41053 {$ELSE ASM_VERSION} //Pascal
41054 procedure TControl.BrushChanged(Sender: PGraphicTool);
41055 begin
41056 fColor := Sender.fData.Color;
41057 if fTmpBrush <> 0 then
41058 begin
41059 DeleteObject( fTmpBrush );
41060 fTmpBrush := 0;
41061 end;
41062 if fPaintDC = 0 then
41063 // only if not in painting already :
41064 Invalidate;
41065 end;
41066 {$ENDIF ASM_VERSION}
41068 {$IFDEF ASM_VERSION}
41069 //[procedure TControl.ApplyFont2Wnd]
41070 procedure TControl.ApplyFont2Wnd;
41072 PUSH EBX
41073 XCHG EBX, EAX
41075 MOV ECX, [EBX].fFont
41076 JECXZ @@exit
41077 XCHG EAX, ECX
41079 MOV ECX, [EBX].fHandle
41080 JECXZ @@0
41082 MOV EDX, [EAX].TGraphicTool.fData.Color
41083 MOV [EBX].fTextColor, EDX
41085 PUSH $FFFF
41086 CALL TGraphicTool.GetHandle
41087 PUSH EAX
41088 PUSH WM_SETFONT
41089 PUSH EBX
41090 CALL Perform
41092 @@0:
41093 XOR ECX, ECX
41094 XCHG ECX, [EBX].fCanvas
41095 JECXZ @@1
41097 XCHG EAX, ECX
41098 CALL TObj.Free
41099 @@1:
41100 MOV ECX, [EBX].fAutoSize
41101 JECXZ @@exit
41102 XCHG EAX, EBX
41103 CALL ECX
41104 @@exit:
41105 POP EBX
41106 end;
41107 {$ELSE ASM_VERSION} //Pascal
41108 procedure TControl.ApplyFont2Wnd;
41109 begin
41110 if fFont <> nil then
41111 begin
41112 if fHandle <> 0 then
41113 begin
41114 fTextColor := fFont.fData.Color;
41115 Perform( WM_SETFONT, FFont.Handle, 1 );
41116 end;
41118 if fCanvas <> nil then
41119 begin
41120 fCanvas.Free;
41121 fCanvas := nil;
41122 end;
41124 if Assigned( fAutoSize ) then
41125 fAutoSize( @Self );
41126 //if assigned( fCanvas ) then
41127 // {fCanvas.fFont :=} fCanvas.fFont.Assign( fFont );
41128 end;
41129 end;
41130 {$ENDIF ASM_VERSION}
41132 {$IFDEF ASM_VERSION}
41133 //[function TControl.ResizeParent]
41134 function TControl.ResizeParent: PControl;
41136 LEA EDX, [TControl.ResizeParentRight]
41137 PUSH EDX
41138 CALL EDX
41139 CALL TControl.ResizeParentBottom
41140 end;
41141 {$ELSE ASM_VERSION} //Pascal
41142 function TControl.ResizeParent: PControl;
41143 begin
41144 ResizeParentBottom;
41145 ResizeParentRight;
41146 // Once again, to fix Windows (or my???) bug with
41147 // incorrect calculating of GetClientRect after
41148 // SetWindowLong( GWL_[EX}STYLE,... )
41149 Result := ResizeParentBottom;
41150 end;
41151 {$ENDIF ASM_VERSION}
41153 {$IFDEF ASM_VERSION}
41154 //[function TControl.ResizeParentBottom]
41155 function TControl.ResizeParentBottom: PControl;
41157 PUSH EAX
41158 PUSH EBX
41159 MOV EBX, [EAX].fParent
41160 TEST EBX, EBX
41161 JZ @@exit
41163 MOV EDX, [EAX].fBoundsRect.Bottom
41164 ADD EDX, [EBX].fMargin
41166 TEST [EBX].fChangedPosSz, 20h
41167 JZ @@1
41169 PUSH EDX
41170 MOV EAX, EBX
41171 CALL GetClientHeight
41172 POP EDX
41174 CMP EDX, EAX
41175 JLE @@exit
41176 @@1:
41177 MOV EAX, EBX
41178 CALL TControl.SetClientHeight
41179 OR [EBX].fChangedPosSz, 20h
41180 @@exit:
41181 POP EBX
41182 POP EAX
41183 end;
41184 {$ELSE ASM_VERSION} //Pascal
41185 function TControl.ResizeParentBottom: PControl;
41186 var NewCH: Integer;
41187 begin
41188 Result := @Self;
41189 if fParent <> nil then
41190 begin
41191 NewCH := BoundsRect.Bottom + fParent.fMargin;
41192 if (fParent.fChangedPosSz and $20) <> 0 then
41193 if NewCH < fParent.ClientHeight then Exit;
41194 fParent.ClientHeight := NewCH;
41195 fParent.fChangedPosSz := fParent.fChangedPosSz or $20;
41196 end;
41197 end;
41198 {$ENDIF ASM_VERSION}
41200 {$IFDEF ASM_VERSION}
41201 //[function TControl.ResizeParentRight]
41202 function TControl.ResizeParentRight: PControl;
41204 PUSH EAX
41205 PUSH EBX
41206 MOV EBX, [EAX].fParent
41207 TEST EBX, EBX
41208 JZ @@exit
41210 MOV EDX, [EAX].fBoundsRect.Right
41211 ADD EDX, [EBX].fMargin
41213 TEST [EBX].fChangedPosSz, 10h
41214 JZ @@1
41216 PUSH EDX
41217 MOV EAX, EBX
41218 CALL GetClientWidth
41219 POP EDX
41221 CMP EDX, EAX
41222 JLE @@exit
41223 @@1:
41224 MOV EAX, EBX
41225 CALL TControl.SetClientWidth
41226 OR [EBX].fChangedPosSz, 10h
41227 @@exit:
41228 POP EBX
41229 POP EAX
41230 end;
41231 {$ELSE ASM_VERSION} //Pascal
41232 function TControl.ResizeParentRight: PControl;
41233 var NewCW: Integer;
41234 begin
41235 Result := @Self;
41236 if fParent <> nil then
41237 begin
41238 NewCW := fBoundsRect.Right + fParent.fMargin;
41239 if (fParent.fChangedPosSz and $10) <> 0 then
41240 if NewCW < fParent.ClientWidth then Exit;
41241 fParent.ClientWidth := NewCW;
41242 fParent.fChangedPosSz := fParent.fChangedPosSz or $10;
41243 end;
41244 end;
41245 {$ENDIF ASM_VERSION}
41247 {$IFDEF ASM_VERSION}
41248 //[function TControl.GetClientHeight]
41249 function TControl.GetClientHeight: Integer;
41251 ADD ESP, -size_TRect
41252 MOV EDX, ESP
41253 CALL TControl.ClientRect
41254 POP EDX
41255 POP ECX // Top
41256 POP EDX
41257 POP EAX // Bottom
41258 SUB EAX, ECX // Result = Bottom - Top
41259 end;
41260 {$ELSE ASM_VERSION} //Pascal
41261 function TControl.GetClientHeight: Integer;
41262 begin
41263 with ClientRect do
41264 Result := Bottom - Top;
41265 end;
41266 {$ENDIF ASM_VERSION}
41268 {$IFDEF ASM_VERSION}
41269 //[function TControl.GetClientWidth]
41270 function TControl.GetClientWidth: Integer;
41272 ADD ESP, -size_TRect
41273 MOV EDX, ESP
41274 CALL TControl.ClientRect
41275 POP ECX // Left
41276 POP EDX
41277 POP EAX // Right
41278 SUB EAX, ECX // Result = Right - Left
41279 POP EDX
41280 end;
41281 {$ELSE ASM_VERSION} //Pascal
41282 function TControl.GetClientWidth: Integer;
41283 begin
41284 with ClientRect do
41285 Result := Right - Left;
41286 end;
41287 {$ENDIF ASM_VERSION}
41289 {$IFDEF ASM_VERSION}
41290 //[procedure TControl.SetClientHeight]
41291 procedure TControl.SetClientHeight(const Value: Integer);
41293 PUSH EBX
41294 PUSH EDX
41296 MOV EBX, EAX
41297 CALL TControl.GetClientHeight
41298 PUSH EAX
41299 MOV EAX, EBX
41300 CALL TControl.GetHeight // EAX = Height
41302 POP EDX // EDX = ClientHeight
41303 SUB EAX, EDX // EAX = Delta
41304 POP EDX // EDX = Value
41305 ADD EDX, EAX // EDX = Value + Delta
41306 XCHG EAX, EBX // EAX = @Self
41307 CALL TControl.SetHeight
41308 POP EBX
41309 end;
41310 {$ELSE ASM_VERSION} //Pascal
41311 procedure TControl.SetClientHeight(const Value: Integer);
41312 var Delta: Integer;
41313 begin
41314 Delta := ClientHeight;
41315 Delta := Height - Delta;
41316 Height := Value + Delta;
41317 end;
41318 {$ENDIF ASM_VERSION}
41320 {$IFDEF ASM_VERSION}
41321 //[procedure TControl.SetClientWidth]
41322 procedure TControl.SetClientWidth(const Value: Integer);
41324 PUSH EBX
41325 PUSH EDX
41327 MOV EBX, EAX
41328 CALL TControl.GetClientWidth
41329 PUSH EAX
41330 MOV EAX, EBX
41331 CALL TControl.GetWidth // EAX = Width
41333 POP EDX // EDX = ClientWidth
41334 SUB EAX, EDX // EAX = Width - ClientWidth
41335 POP EDX // EDX = Value
41336 ADD EDX, EAX // EDX = Value + Delta
41337 XCHG EAX, EBX // EAX = @Self
41338 CALL TControl.SetWidth
41339 POP EBX
41340 end;
41341 {$ELSE ASM_VERSION} //Pascal
41342 procedure TControl.SetClientWidth(const Value: Integer);
41343 var Delta: Integer;
41344 begin
41345 Delta := ClientWidth;
41346 Delta := Width - Delta;
41347 Width := Value + Delta;
41348 end;
41349 {$ENDIF ASM_VERSION}
41351 {$IFDEF ASM_VERSION}
41352 //[function TControl.CenterOnParent]
41353 function TControl.CenterOnParent: PControl;
41355 PUSHAD
41357 XCHG ESI, EAX
41358 MOV ECX, [ESI].fParent
41359 JECXZ @@1
41360 CMP [ESI].fIsControl, 0
41361 JNZ @@2
41363 @@1:
41364 PUSH SM_CYSCREEN
41365 CALL GetSystemMetrics
41366 PUSH EAX
41368 PUSH SM_CXSCREEN
41369 CALL GetSystemMetrics
41370 PUSH EAX
41372 PUSH 0
41373 PUSH 0 // ESP -> Rect( 0, 0, CX, CY )
41375 JMP @@3
41377 @@2: ADD ESP, -size_TRect
41378 MOV EDX, ESP
41379 XCHG EAX, ECX
41380 CALL TControl.ClientRect
41381 // ESP -> ClientRect
41382 @@3: MOV EAX, ESI
41383 CALL GetWindowHandle
41385 MOV EAX, ESI
41386 CALL GetWidth
41388 POP EDX // left
41389 ADD EAX, EDX // + width
41391 POP EDI // top
41392 POP EDX // right
41394 SUB EDX, EAX
41395 SAR EDX, 1
41397 MOV EAX, ESI
41398 CALL SetLeft
41400 MOV EAX, ESI
41401 CALL GetHeight
41403 ADD EAX, EDI // height + top
41405 POP EDX // bottom
41406 SUB EDX, EAX
41407 SAR EDX, 1
41409 XCHG EAX, ESI
41410 CALL SetTop
41412 POPAD
41413 end;
41414 {$ELSE ASM_VERSION} //Pascal
41415 function TControl.CenterOnParent: PControl;
41416 var PCR: TRect;
41417 begin
41418 Result := @Self;
41419 if (fParent = nil) or not fIsControl then
41420 PCR := MakeRect( 0, 0, GetSystemMetrics( SM_CXSCREEN ), GetSystemMetrics( SM_CYSCREEN ) )
41421 else
41422 PCR := fParent.ClientRect;
41423 GetWindowHandle;
41424 Left := (PCR.Right - PCR.Left - Width) div 2;
41425 Top := (PCR.Bottom - PCR.Top - Height) div 2;
41426 end;
41427 {$ENDIF ASM_VERSION}
41429 {$IFDEF ASM_noVERSION}
41430 //[function TControl.GetHasBorder]
41431 function TControl.GetHasBorder: Boolean;
41432 const style_mask = WS_BORDER or WS_THICKFRAME or WS_DLGFRAME;
41434 CALL UpdateWndStyles
41435 MOV EAX, [EAX].fStyle
41436 AND EAX, style_mask
41437 SETNZ AL
41438 end;
41439 {$ELSE ASM_VERSION} //Pascal
41440 function TControl.GetHasBorder: Boolean;
41441 begin
41442 UpdateWndStyles;
41443 Result := LongBool( fStyle and (WS_BORDER or WS_THICKFRAME or WS_DLGFRAME))
41444 or LongBool( fExStyle and WS_EX_CLIENTEDGE );
41445 end;
41446 {$ENDIF ASM_VERSION}
41448 {$IFDEF ASM_noVERSION} // YS
41449 //[procedure TControl.SetHasBorder]
41450 procedure TControl.SetHasBorder(const Value: Boolean);
41451 const style_mask = WS_BORDER or WS_THICKFRAME or WS_DLGFRAME or WS_CAPTION
41452 or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or WS_SYSMENU;
41453 exstyle_mask = not (WS_EX_CONTROLPARENT or WS_EX_DLGMODALFRAME
41454 or WS_EX_WINDOWEDGE or WS_EX_CLIENTEDGE);
41457 PUSH EAX
41458 PUSH EDX
41460 CALL GetHasBorder
41461 POP ECX
41462 CMP AL, CL
41464 POP EAX
41465 JZ @@exit
41467 MOV EDX, [EAX].fStyle
41468 DEC CL
41469 MOVZX ECX, [EAX].fIsControl
41470 JNZ @@1
41472 OR EDX, WS_THICKFRAME
41473 INC ECX
41474 LOOP @@set_style
41475 OR EDX, style_mask
41476 JMP @@set_style
41478 @@1: AND EDX, not style_mask
41479 INC ECX
41480 LOOP @@2
41481 OR EDX, WS_POPUP
41483 @@2: PUSH EDX
41485 MOV EDX, [EAX].fExStyle
41486 AND EDX, exstyle_mask
41488 PUSH EAX
41489 CALL SetExStyle
41490 POP EAX
41492 POP EDX
41493 @@set_style:
41494 CALL SetStyle
41495 @@exit:
41496 end;
41497 {$ELSE ASM_VERSION} //Pascal
41498 procedure TControl.SetHasBorder(const Value: Boolean);
41499 var NewStyle: DWORD;
41500 begin
41501 if Value = GetHasBorder then Exit;
41502 {if Value then
41503 begin
41504 NewStyle := fStyle or WS_THICKFRAME;
41505 if not fIsControl then
41506 NewStyle := NewStyle or WS_BORDER or
41507 WS_DLGFRAME or WS_CAPTION or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or
41508 WS_SYSMENU;
41509 Style := NewStyle;
41510 end}
41511 if Value then
41512 begin
41513 if not fIsControl then
41514 Style := fStyle or WS_THICKFRAME or WS_BORDER or
41515 WS_DLGFRAME or WS_CAPTION or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or
41516 WS_SYSMENU
41517 else
41518 if fCtl3D then
41519 ExStyle := fExStyle or WS_EX_CLIENTEDGE
41520 else
41521 Style := fStyle or WS_BORDER;
41523 else
41524 begin
41525 NewStyle := fStyle and not (WS_BORDER or WS_THICKFRAME or WS_DLGFRAME or WS_CAPTION
41526 or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or WS_SYSMENU);
41527 if not fIsControl then NewStyle := NewStyle or WS_POPUP;
41528 Style := NewStyle;
41529 ExStyle := fExStyle and not (WS_EX_CONTROLPARENT or WS_EX_DLGMODALFRAME
41530 or WS_EX_WINDOWEDGE or WS_EX_CLIENTEDGE);
41531 end;
41532 end;
41533 {$ENDIF ASM_VERSION}
41535 {$IFDEF ASM_VERSION}
41536 //[function TControl.GetHasCaption]
41537 function TControl.GetHasCaption: Boolean;
41538 const style_mask1 = (WS_POPUP or WS_DLGFRAME) shr 16;
41539 style_mask2 = WS_CAPTION shr 16;
41541 CALL UpdateWndStyles
41542 MOV ECX, [EAX].fStyle + 2
41543 MOV EDX, ECX
41544 MOV AL, 1
41545 AND DX, style_mask1
41546 JZ @@1
41547 AND CX, style_mask2
41548 JNZ @@1
41549 XOR EAX, EAX
41550 @@1:
41551 end;
41552 {$ELSE ASM_VERSION} //Pascal
41553 function TControl.GetHasCaption: Boolean;
41554 begin
41555 UpdateWndStyles;
41556 Result := not LongBool( fStyle and (WS_POPUP or WS_DLGFRAME))
41557 or LongBool( fStyle and WS_CAPTION);
41558 end;
41559 {$ENDIF ASM_VERSION}
41561 {$IFDEF ASM_VERSION}
41562 //[procedure TControl.SetHasCaption]
41563 procedure TControl.SetHasCaption(const Value: Boolean);
41564 const style_mask = not (WS_BORDER or WS_THICKFRAME or WS_DLGFRAME or WS_CAPTION
41565 or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or WS_SYSMENU);
41566 exstyle_mask = not (WS_EX_CONTROLPARENT or WS_EX_DLGMODALFRAME
41567 or WS_EX_WINDOWEDGE or WS_EX_CLIENTEDGE);
41569 PUSH EAX
41570 PUSH EDX
41572 CALL GetHasCaption
41573 POP ECX
41574 CMP AL, CL
41576 POP EAX
41577 JZ @@exit // Value = HasCaption
41579 MOV EDX, [EAX].fStyle
41580 DEC CL
41581 JNZ @@1 // if not Value -> @@1
41583 AND EDX, not WS_POPUP
41584 OR EDX, WS_CAPTION
41585 JMP @@set_style
41587 @@1:
41588 CMP [EAX].fIsControl, 0
41589 JNZ @@2 // if fIsControl -> @@2
41591 AND EDX, not (WS_CAPTION or WS_SYSMENU)
41592 OR EDX, WS_POPUP
41593 JMP @@3
41595 @@2:
41596 AND EDX, not WS_CAPTION
41597 OR EDX, WS_DLGFRAME
41599 @@3:
41600 PUSH EDX
41602 MOV EDX, [EAX].fExStyle
41603 OR EDX, WS_EX_DLGMODALFRAME
41605 PUSH EAX
41606 CALL SetExStyle
41607 POP EAX
41609 POP EDX
41610 @@set_style:
41611 CALL SetStyle
41612 @@exit:
41613 end;
41614 {$ELSE ASM_VERSION} //Pascal
41615 procedure TControl.SetHasCaption(const Value: Boolean);
41616 begin
41617 if Value = GetHasCaption then Exit;
41618 if Value then
41619 begin
41620 Style := fStyle and not (WS_POPUP or WS_DLGFRAME) or WS_CAPTION;
41622 else
41623 begin
41624 if fIsControl then
41625 Style := fStyle and not WS_CAPTION or WS_DLGFRAME
41626 else
41627 Style := fStyle and not (WS_CAPTION or WS_SYSMENU) or WS_POPUP;
41628 ExStyle := fExStyle or WS_EX_DLGMODALFRAME;
41629 end;
41630 end;
41631 {$ENDIF ASM_VERSION}
41633 {$IFDEF ASM_VERSION}
41634 //[function TControl.GetCanResize]
41635 function TControl.GetCanResize: Boolean;
41637 MOV AL, [EAX].fPreventResize
41638 {$IFDEF PARANOIA}
41639 DB $34,$01
41640 {$ELSE}
41641 XOR AL, 1
41642 {$ENDIF}
41643 end;
41644 {$ELSE ASM_VERSION} //Pascal
41645 function TControl.GetCanResize: Boolean;
41646 begin
41647 //UpdateWndStyles;
41648 //Result := LongBool( fStyle and WS_THICKFRAME);
41649 Result := not fPreventResize;
41650 end;
41651 {$ENDIF ASM_VERSION}
41653 //[function WndProcCanResize]
41654 function WndProcCanResize( Sender: PControl; var M: TMsg; var Rslt: Integer ): Boolean;
41655 var W, H: Integer;
41656 P: PMinMaxInfo;
41657 begin
41658 if not Sender.CanResize then
41659 if M.message = WM_GETMINMAXINFO then
41660 begin
41661 Rslt := Sender.CallDefWndProc( M );
41662 W := Sender.FFixWidth;
41663 H := Sender.FFixHeight;
41664 P := Pointer( M.lParam );
41665 P.ptMinTrackSize.x := W;
41666 P.ptMinTrackSize.y := H;
41667 P.ptMaxTrackSize := P.ptMinTrackSize;
41668 Result := True; // stop further processing (prevent resizing)
41669 Exit;
41671 else
41672 if M.message = WM_NCHITTEST then
41673 begin
41674 Rslt := Sender.CallDefWndProc( M );
41675 if (Rslt >= 10) and (Rslt <= 17) then
41676 begin
41677 Rslt := {-}HTBORDER{+}{++}(*18{HTBORDER}*){--};
41678 Result := True;
41679 exit;
41680 end;
41681 end;
41682 Result := False; // continue message processing
41683 end;
41685 {$IFDEF ASM_VERSION}
41686 //[procedure TControl.SetCanResize]
41687 procedure TControl.SetCanResize( const Value: Boolean );
41689 PUSH EBX
41690 MOV EBX, EAX
41692 CALL GetCanResize
41693 CMP AL, DL
41695 JZ @@exit // Value = CanResize
41696 MOV [EBX].fPreventResize, AL
41697 TEST DL, DL
41699 MOV EDX, [EBX].fStyle
41700 JZ @@set_thick
41702 OR EDX, WS_THICKFRAME
41703 JMP @@set_style
41705 @@set_thick:
41706 AND EDX, not WS_THICKFRAME
41708 @@set_style:
41709 MOV EAX, EBX
41710 CALL SetStyle
41712 MOV EAX, EBX
41713 CALL GetWindowHandle
41715 MOV EAX, EBX
41716 CALL GetWidth
41717 MOV [EBX].FFixWidth, EAX
41719 MOV EAX, EBX
41720 CALL GetHeight
41721 MOV [EBX].FFixHeight, EAX
41723 XCHG EAX, EBX
41724 MOV EDX, offset[WndProcCanResize]
41725 CALL TControl.AttachProc
41726 @@exit:
41727 POP EBX
41728 end;
41729 {$ELSE ASM_VERSION} //Pascal
41730 procedure TControl.SetCanResize( const Value: Boolean );
41731 begin
41732 if Value = CanResize then Exit;
41733 fPreventResize := not Value;
41734 if Value then
41735 Style := Style or WS_THICKFRAME
41736 else
41737 Style := Style and not WS_THICKFRAME;
41738 GetWindowHandle;
41739 FFixWidth := Width;
41740 FFixHeight := Height;
41741 AttachProc( WndProcCanResize );
41742 end;
41743 {$ENDIF ASM_VERSION}
41745 {$IFDEF ASM_VERSION}
41746 //[function TControl.GetStayOnTop]
41747 function TControl.GetStayOnTop: Boolean;
41749 CALL UpdateWndStyles
41750 TEST byte ptr [EAX].fExStyle, WS_EX_TOPMOST
41751 SETNZ AL
41752 end;
41753 {$ELSE ASM_VERSION} //Pascal
41754 function TControl.GetStayOnTop: Boolean;
41755 begin
41756 UpdateWndStyles;
41757 Result := LongBool( fExStyle and WS_EX_TOPMOST);
41758 end;
41759 {$ENDIF ASM_VERSION}
41761 {$IFDEF ASM_VERSION}
41762 //[procedure TControl.SetStayOnTop]
41763 procedure TControl.SetStayOnTop(const Value: Boolean);
41765 PUSH EAX
41766 PUSH EDX
41768 CALL GetStayOnTop
41769 POP ECX
41770 MOVZX ECX, CL
41771 CMP AL, CL
41773 POP EAX
41774 JZ @@exit // Value = StayOnTop
41776 MOV EDX, [EAX].fHandle
41777 TEST EDX, EDX
41778 JZ @@1
41780 PUSH SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE
41781 XOR EAX, EAX
41782 PUSH EAX
41783 PUSH EAX
41784 PUSH EAX
41785 PUSH EAX
41786 DEC ECX
41787 DEC ECX
41788 PUSH ECX
41790 PUSH EDX
41791 CALL SetWindowPos
41794 @@1:
41795 JECXZ @@1and
41797 OR byte ptr [EAX].fExStyle, WS_EX_TOPMOST
41800 @@1and: AND byte ptr [EAX].fExStyle, not WS_EX_TOPMOST
41802 @@exit:
41803 end;
41804 {$ELSE ASM_VERSION} //Pascal
41805 procedure TControl.SetStayOnTop(const Value: Boolean);
41806 begin
41807 if Value = GetStayOnTop then Exit;
41808 if fHandle <> 0 then
41809 if Value then
41810 SetWindowPos( fHandle, HWND_TOPMOST, 0,0,0,0,
41811 SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE )
41812 else
41813 SetWindowPos( fHandle, HWND_NOTOPMOST, 0,0,0,0,
41814 SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE )
41815 else
41816 if Value then fExStyle := fExStyle or WS_EX_TOPMOST
41817 else fExStyle := fExStyle and not WS_EX_TOPMOST;
41818 end;
41819 {$ENDIF ASM_VERSION}
41821 {$IFDEF ASM_VERSION}
41822 //[function TControl.UpdateWndStyles]
41823 function TControl.UpdateWndStyles: PControl;
41825 MOV ECX, [EAX].fHandle
41826 JECXZ @@exit
41828 PUSH EBX
41830 XCHG EBX, EAX
41831 PUSH GCL_STYLE
41832 PUSH ECX
41834 PUSH GWL_EXSTYLE
41835 PUSH ECX
41837 PUSH GWL_STYLE
41838 PUSH ECX
41840 CALL GetWindowLong
41841 MOV [EBX].fStyle, EAX
41843 CALL GetWindowLong
41844 MOV [EBX].fExStyle, EAX
41846 CALL GetClassLong
41847 MOV [EBX].fClsStyle, EAX
41848 XCHG EAX, EBX
41849 POP EBX
41850 @@exit:
41851 end;
41852 {$ELSE ASM_VERSION} //Pascal
41853 function TControl.UpdateWndStyles: PControl;
41854 begin
41855 Result := @Self;
41856 if fHandle = 0 then Exit;
41857 fStyle := GetWindowLong( fHandle, GWL_STYLE );
41858 fExStyle := GetWindowLong( fHandle, GWL_EXSTYLE );
41859 fClsStyle := GetClassLong( fHandle, GCL_STYLE );
41860 end;
41861 {$ENDIF ASM_VERSION}
41863 {$IFDEF ASM_VERSION}
41864 //[function TControl.GetChecked]
41865 function TControl.GetChecked: Boolean;
41867 TEST [EAX].fBitBtnOptions, 8 //1 shl Ord(bboFixed)
41868 JZ @@1
41869 MOV AL, [EAX].fChecked
41871 @@1:
41872 PUSH 0
41873 PUSH 0
41874 PUSH BM_GETCHECK
41875 PUSH EAX
41876 CALL Perform
41877 @@exit:
41878 end;
41879 {$ELSE ASM_VERSION} //Pascal
41880 function TControl.GetChecked: Boolean;
41881 begin
41882 if bboFixed in fBitBtnOptions then
41883 Result := fChecked
41884 else
41885 Result := LongBool( Perform( BM_GETCHECK, 0, 0 ) ) ; //= BST_CHECKED;
41886 end;
41887 {$ENDIF ASM_VERSION}
41889 {$IFDEF ASM_VERSION}
41890 //[procedure TControl.Set_Checked]
41891 procedure TControl.Set_Checked(const Value: Boolean);
41893 TEST [EAX].fBitBtnOptions, 8 //1 shl Ord(bboFixed)
41894 JZ @@1
41895 MOV [EAX].fChecked, DL
41896 JMP Invalidate
41897 @@1:
41898 PUSH 0
41899 MOVZX EDX, DL
41900 PUSH EDX
41901 PUSH BM_SETCHECK
41902 PUSH EAX
41903 Call Perform
41904 end;
41905 {$ELSE ASM_VERSION} //Pascal
41906 procedure TControl.Set_Checked(const Value: Boolean);
41907 begin
41908 if bboFixed in fBitBtnOptions then
41909 begin
41910 fChecked := //not fChecked;
41911 Value;
41912 Invalidate;
41914 else
41915 Perform( BM_SETCHECK, Integer( Value ), 0 );
41916 end;
41917 {$ENDIF ASM_VERSION}
41919 //[function TControl.SetChecked]
41920 function TControl.SetChecked(const Value: Boolean): PControl;
41921 begin
41922 Perform( BM_SETCHECK, Integer( Value ), 0 );
41923 Result := @Self;
41924 end;
41926 {$IFDEF ASM_VERSION}
41927 //[function TControl.SetRadioCheckedOld]
41928 function TControl.SetRadioCheckedOld: PControl;
41930 PUSH EAX
41931 MOV ECX, [EAX].fParent
41932 JECXZ @@exit
41934 PUSH [EAX].fMenu
41935 PUSH [ECX].fRadioLast
41936 PUSH [ECX].fRadio1st
41937 MOV EAX, ECX
41938 CALL GetWindowHandle
41939 PUSH EAX
41940 CALL CheckRadioButton
41941 @@exit:
41942 POP EAX
41943 end;
41944 {$ELSE ASM_VERSION} //Pascal
41945 function TControl.SetRadioCheckedOld: PControl;
41946 begin
41947 Result := @Self;
41948 if fParent = nil then Exit;
41949 CheckRadioButton( fParent.GetWindowHandle,
41950 fParent.fRadio1st,
41951 fParent.fRadioLast,
41952 fMenu );
41953 end;
41954 {$ENDIF ASM_VERSION}
41957 //[function TControl.SetRadioChecked]
41958 function TControl.SetRadioChecked: PControl;
41959 begin
41960 Click;
41961 Result := @Self;
41962 end;
41965 //[procedure TControl.Click]
41966 procedure TControl.Click;
41967 begin
41968 if (fCommandActions.aClick <> 0) or
41969 (fCommandActions.aEnter = BN_SETFOCUS) then
41970 Perform( WM_COMMAND, (fCommandActions.aClick shl 16) or fMenu,
41971 GetWindowHandle )
41972 else
41973 begin
41974 Perform( WM_LBUTTONDOWN, MK_LBUTTON, 0 );
41975 Perform( WM_LBUTTONUP, MK_LBUTTON, 0 );
41976 end;
41977 end;
41979 {$IFDEF ASM_VERSION}
41980 //[function TControl.GetSelStart]
41981 function TControl.GetSelStart: Integer;
41983 MOVZX ECX, [EAX].fCommandActions.aGetSelRange
41984 JECXZ @@1
41986 XOR EDX, EDX
41987 PUSH EDX
41988 PUSH EDX
41989 PUSH ECX
41990 PUSH EAX
41991 CALL Perform
41992 CWDE
41995 @@1:
41996 MOVZX ECX, [EAX].fCommandActions.aExGetSelRange
41997 JECXZ @@exit
41998 XCHG EAX, ECX
42000 PUSH EDX
42001 PUSH EDX
42002 PUSH ESP
42003 PUSH EDX
42004 PUSH EAX
42005 PUSH ECX
42006 CALL Perform
42007 POP ECX
42008 POP EDX
42010 @@exit:
42011 XCHG EAX, ECX
42012 end;
42013 {$ELSE ASM_VERSION} //Pascal
42014 function TControl.GetSelStart: Integer;
42015 var SR: TCharRange;
42016 begin
42017 Result := 0;
42018 if fCommandActions.aGetSelRange <> 0 then
42019 Result := LoWord( Perform( fCommandActions.aGetSelRange, 0, 0 ) )
42020 else
42021 if fCommandActions.aExGetSelRange <> 0 then
42022 begin
42023 Perform( fCommandActions.aExGetSelRange, 0, Integer( @SR ) );
42024 Result := SR.cpMin;
42025 end;
42026 end;
42027 {$ENDIF ASM_VERSION}
42029 //[procedure TControl.SetSelStart]
42030 procedure TControl.SetSelStart(const Value: Integer);
42031 begin
42032 ItemSelected[ Value ] := True;
42033 end;
42035 {$IFDEF ASM_VERSION}
42036 //[function TControl.GetSelLength]
42037 function TControl.GetSelLength: Integer;
42039 XOR EDX, EDX
42040 MOVZX ECX, word ptr[EAX].fCommandActions.aGetSelCount
42041 JECXZ @@check_ex
42043 PUSH ECX
42044 AND CH, $7F
42045 PUSH EDX
42046 PUSH EDX
42047 PUSH ECX
42048 PUSH EAX
42049 CALL Perform
42050 POP ECX
42051 SHL CH, 1
42052 JC @@fin_EAX
42054 CMP EAX, 32768
42055 JL @@2
42057 PUSH EAX
42058 POP DX
42059 POP AX
42060 SUB AX, DX
42061 MOVZX EAX, AX
42062 @@fin_EAX:
42065 @@check_ex:
42066 MOVZX ECX, [EAX].fCommandActions.aExGetSelRange
42067 JECXZ @@ret_0
42068 PUSH EDX
42069 PUSH EDX
42070 PUSH ESP
42071 PUSH EDX
42072 PUSH ECX
42073 PUSH EAX
42074 CALL Perform
42075 POP EDX
42076 POP EAX
42077 SUB EAX, EDX
42080 @@ret_0:
42081 XOR EAX, EAX
42082 //RET
42084 @@2: TEST EAX, EAX
42085 JL @@ret_0
42086 end;
42087 {$ELSE ASM_VERSION} //Pascal
42088 function TControl.GetSelLength: Integer;
42089 var SR: TCharRange;
42090 begin
42091 Result := 0;
42092 if fCommandActions.aGetSelCount <> 0 then
42093 begin
42094 Result := Perform( fCommandActions.aGetSelCount and $7FFF, 0, 0 );
42095 if (fCommandActions.aGetSelCount and $8000) = 0 then
42096 if Result >= 32768 then
42097 Result := HiWord( Result ) - LoWord( Result )
42098 else
42099 if Result < 0 then
42100 Result := 0;
42102 else
42103 if fCommandActions.aExGetSelRange <> 0 then
42104 begin
42105 Perform( fCommandActions.aExGetSelRange, 0, Integer( @SR ) );
42106 Result := SR.cpMax - SR.cpMin;
42107 end;
42108 end;
42109 {$ENDIF ASM_VERSION}
42111 {$IFDEF ASM_VERSION}
42112 //[procedure TControl.SetSelLength]
42113 procedure TControl.SetSelLength(const Value: Integer);
42115 PUSH EBP
42116 MOV EBP, ESP
42117 PUSH EAX
42118 PUSH EDX
42119 CALL GetSelStart
42120 POP ECX
42121 POP EDX
42122 ADD ECX, EAX
42123 PUSH ECX
42124 MOVZX ECX, [EDX].fCommandActions.aSetSelRange
42125 JECXZ @@check_ex
42126 PUSH EAX
42127 JMP @@perform
42129 @@check_ex:
42130 MOVZX ECX, [EDX].fCommandActions.aExSetSelRange
42131 JECXZ @@exit
42132 PUSH EAX
42133 PUSH ESP
42134 PUSH 0
42135 @@perform:
42136 PUSH ECX
42137 PUSH EDX
42138 CALL Perform
42139 @@exit: MOV ESP, EBP
42140 POP EBP
42141 end;
42142 {$ELSE ASM_VERSION} //Pascal
42143 procedure TControl.SetSelLength(const Value: Integer);
42145 SR: TCharRange;
42146 begin
42147 SR.cpMin := GetSelStart;
42148 SR.cpMax := SR.cpMin + Value;
42149 if Value < 0 then
42150 SR.cpMax := -1;
42151 if fCommandActions.aSetSelRange <> 0 then
42152 Perform( fCommandActions.aSetSelRange, SR.cpMin, SR.cpMax )
42153 else
42154 if fCommandActions.aExSetSelRange <> 0 then
42155 Perform( fCommandActions.aExSetSelRange, 0, Integer( @SR ) );
42156 // Preform( EM_SCROLLCARET, 0, 0 );
42157 end;
42158 {$ENDIF ASM_VERSION}
42160 {$IFDEF ASM_VERSION}
42161 //[function TControl.GetItems]
42162 function TControl.GetItems(Idx: Integer): String;
42164 PUSH ESI
42165 PUSH EDI
42166 PUSH EBX
42167 PUSH EBP
42168 MOV EBP, ESP
42170 MOV EBX, EAX // @Self
42171 MOV ESI, EDX // Idx
42172 MOV EDI, ECX // @Result
42174 CALL Item2Pos
42175 PUSH 0 // push 0
42176 PUSH EAX // store Pos
42178 XCHG EDX, EAX
42179 MOV EAX, EBX
42180 CALL Pos2Item // EAX = Idx'
42181 XCHG ESI, EAX // ESI = Idx'
42183 XOR EAX, EAX
42184 MOVZX ECX, [EBX].fCommandActions.aGetItemLength
42185 JECXZ @@ret_empty
42187 PUSH ECX // push aGetItemLength
42189 PUSH EBX
42190 CALL Perform
42192 TEST EAX, EAX
42193 JZ @@ret_empty
42195 PUSH EAX // save L
42196 ADD EAX, 4
42198 CALL System.@GetMem // GetMem( L+4 )
42199 POP EDX // restore L
42200 MOV byte ptr [EAX], 0
42201 MOVZX ECX, [EBX].fCommandActions.aGetItemText
42202 JECXZ @@ret_buf
42204 PUSH EDX // save L
42205 MOV word ptr [EAX], DX
42207 PUSH EAX
42208 PUSH EAX // push Buf
42209 PUSH ESI // push Idx
42211 PUSH ECX // push aGetItemText
42212 PUSH EBX
42213 CALL Perform
42214 POP EAX
42216 POP EDX
42217 @@ret_buf:
42218 MOV byte ptr [EAX + EDX], 0 // Buf[ L ] := #0
42220 @@ret_empty: // EAX = 0
42221 XCHG EDX, EAX
42222 MOV EAX, EDI
42223 PUSH EDX
42224 CALL System.@LStrFromPChar
42225 POP ECX
42226 JECXZ @@exit
42227 XCHG EAX, ECX
42228 CALL System.@FreeMem
42230 @@exit:
42231 MOV ESP, EBP
42232 POP EBP
42233 POP EBX
42234 POP EDI
42235 POP ESI
42236 end;
42237 {$ELSE ASM_VERSION} //Pascal
42238 function TControl.GetItems(Idx: Integer): String;
42239 var L, Pos: Integer;
42240 Buf: PChar;
42241 begin
42242 Result := '';
42243 Pos := Item2Pos( Idx );
42244 Idx := Pos2Item( Pos );
42245 if fCommandActions.aGetItemLength <> 0 then
42246 L := Perform( fCommandActions.aGetItemLength, Pos, 0 )
42247 else
42248 Exit;
42249 if L = 0 then Exit;
42250 GetMem( Buf, L + 4 );
42251 PWORD( Buf )^ := L + 1;
42252 if fCommandActions.aGetItemText <> 0 then
42253 Perform( fCommandActions.aGetItemText, Idx, Integer( Buf ) );
42254 Buf[ L ] := #0;
42255 Result := Buf;
42256 FreeMem( Buf );
42257 end;
42258 {$ENDIF ASM_VERSION}
42260 {$IFDEF ASM_VERSION}
42261 //[procedure TControl.SetItems]
42262 procedure TControl.SetItems(Idx: Integer; const Value: String);
42264 PUSH EDI
42265 PUSH EBX
42266 XCHG EBX, EAX
42267 XCHG EDI, EDX // EDI = Idx
42268 CALL ECX2PChar
42269 PUSH ECX // @Value[1]
42271 MOVZX ECX, [EBX].fCommandActions.aSetItemText
42272 JECXZ @@1
42274 PUSH 0
42275 PUSH ECX
42277 MOV EDX, EDI
42278 MOV EAX, EBX
42279 CALL Item2Pos
42280 PUSH EAX // store Strt
42282 MOV EDX, EDI
42283 INC EDX
42284 MOV EAX, EBX
42285 CALL Item2Pos
42286 POP EDX // EDX = Strt
42288 SUB EAX, EDX
42289 PUSH EAX // store L
42291 MOV EAX, EBX
42292 CALL SetSelStart
42294 POP EDX // EDX = L
42295 PUSH EBX // prepare @Self for Perform
42296 XCHG EAX, EBX
42297 CALL SetSelLength
42299 // @Value[1] already in stack,
42300 // 0 already in stack
42301 // aSetItemText already in stack
42302 // @Self already in stack
42304 CALL Perform
42305 JMP @@exit
42307 @@1: // @Value[1] in stack already
42308 POP EDX
42309 MOVZX ECX, [EBX].fCommandActions.aDeleteItem
42310 JECXZ @@exit
42312 {$IFNDEF NOT_FIX_CURINDEX}
42313 PUSH ESI
42314 PUSH EBP
42316 PUSH EDX
42318 MOV EAX, EBX // +AK
42319 CALL GetCurIndex // +AK
42320 XCHG ESI, EAX // ESI = TmpCurIdx
42322 MOV EAX, EBX
42323 MOV EDX, EDI
42324 CALL GetItemData
42325 XCHG EBP, EAX // EBP = TmpData
42327 MOV EDX, EDI
42328 MOV EAX, EBX
42329 CALL Delete
42331 MOV EAX, EBX // *AK
42332 MOV EDX, EDI
42333 POP ECX
42334 CALL Insert
42336 MOV ECX, EBP // ECX = TmpData
42337 MOV EDX, EDI
42338 MOV EAX, EBX
42339 CALL SetItemData
42341 XCHG EAX, EBX // +AK
42342 MOV EDX, ESI // +AK
42343 CALL SetCurIndex // +AK
42345 POP EBP
42346 POP ESI
42347 {$ELSE NOT_FIX_CURINDEX}
42348 PUSH EDX
42350 MOV EDX, EDI
42351 MOV EAX, EBX
42352 CALL Delete
42354 XCHG EAX, EBX
42355 XCHG EDX, EDI
42357 POP ECX
42358 CALL Insert
42359 {$ENDIF NOT_FIX_CURINDEX}
42361 @@exit:
42362 POP EBX
42363 POP EDI
42364 end;
42365 {$ELSE ASM_VERSION} //Pascal
42366 procedure TControl.SetItems(Idx: Integer; const Value: String);
42367 var Strt, L : Integer;
42368 {$IFNDEF NOT_FIX_CURINDEX}
42369 TmpCurIdx: Integer; // AK - Andrzey Kubasek
42370 TmpData: DWORD;
42371 {$ENDIF NOT_FIX_CURINDEX}
42372 begin
42373 if fCommandActions.aSetItemText <> 0 then
42374 begin
42375 Strt := Item2Pos( Idx );
42376 L := Item2Pos( Idx + 1 ) - Strt;
42377 SelStart := Strt;
42378 SelLength := L;
42379 Perform( fCommandActions.aSetItemText, 0, Integer( PChar( Value ) ) );
42381 else
42382 if fCommandActions.aDeleteItem <> 0 then
42383 begin
42384 {$IFNDEF NOT_FIX_CURINDEX}
42385 TmpCurIdx := CurIndex; // +AK
42386 TmpData := ItemData[ Idx ];
42387 {$ENDIF}
42388 Delete( Idx );
42389 Insert( Idx, Value );
42390 {$IFNDEF NOT_FIX_CURINDEX}
42391 CurIndex := TmpCurIdx; //+AK
42392 ItemData[ Idx ] := TmpData;
42393 {$ENDIF}
42394 end;
42395 end;
42396 {$ENDIF ASM_VERSION}
42398 {$IFDEF ASM_VERSION}
42399 //[function TControl.GetItemsCount]
42400 function TControl.GetItemsCount: Integer;
42402 PUSH 0
42403 MOVZX ECX, [EAX].fCommandActions.aGetCount
42404 JECXZ @@ret_0
42405 PUSH 0
42406 PUSH ECX
42407 PUSH EAX
42408 CALL Perform
42409 PUSH EAX
42411 @@ret_0:
42412 POP EAX
42413 end;
42414 {$ELSE ASM_VERSION} //Pascal
42415 function TControl.GetItemsCount: Integer;
42416 begin
42417 Result := 0;
42418 {$IFDEF DEBUG}
42420 {$ENDIF}
42421 if fCommandActions.aGetCount = 0 then Exit;
42422 Result := Perform( fCommandActions.aGetCount, 0, 0 );
42423 {$IFDEF DEBUG}
42424 except
42426 int 3
42427 end;
42428 end;
42429 {$ENDIF}
42430 end;
42431 {$ENDIF ASM_VERSION}
42434 //[procedure TControl.SetItemsCount]
42435 procedure TControl.SetItemsCount(const Value: Integer);
42436 begin
42437 if fCommandActions.aSetCount = 0 then Exit;
42438 Perform( fCommandActions.aSetCount, Value, 0 );
42439 end;
42441 //[PROCEDURE HelpConvertItem2Pos]
42442 {$IFDEF ASM_VERSION}
42443 procedure HelpConvertItem2Pos;
42445 JECXZ @@exit
42446 PUSH 0
42447 PUSH EDX
42448 PUSH ECX
42449 PUSH EAX
42450 CALL TControl.Perform
42451 XOR EDX, EDX
42452 TEST EAX, EAX
42453 JL @@exit
42455 @@exit:
42456 MOV EAX, EDX
42457 end;
42458 {$ENDIF ASM_VERSION}
42459 //[END HelpConvertItem2Pos]
42461 {$IFDEF ASM_VERSION}
42462 //[function TControl.Item2Pos]
42463 function TControl.Item2Pos(ItemIdx: Integer): Integer;
42465 MOVZX ECX, [EAX].fCommandActions.aItem2Pos
42466 JMP HelpConvertItem2Pos
42467 end;
42468 {$ELSE ASM_VERSION} //Pascal
42469 function TControl.Item2Pos(ItemIdx: Integer): Integer;
42470 begin
42471 Result := ItemIdx;
42472 if fCommandActions.aItem2Pos <> 0 then
42473 begin
42474 Result := Perform( fCommandActions.aItem2Pos, ItemIdx, 0 );
42475 if Result < 0 then Result := 0;
42476 end;
42477 end;
42478 {$ENDIF ASM_VERSION}
42480 {$IFDEF ASM_VERSION}
42481 //[function TControl.Pos2Item]
42482 function TControl.Pos2Item(Pos: Integer): Integer;
42484 MOVZX ECX, [EAX].fCommandActions.aPos2Item
42485 JMP HelpConvertItem2Pos
42486 end;
42487 {$ELSE ASM_VERSION} //Pascal
42488 function TControl.Pos2Item(Pos: Integer): Integer;
42489 begin
42490 Result := Pos;
42491 if fCommandActions.aPos2Item <> 0 then
42492 Result := Perform( fCommandActions.aPos2Item, Pos, 0 );
42493 end;
42494 {$ENDIF ASM_VERSION}
42496 //[function WndProcTabChar]
42497 function WndProcTabChar( Sender: PControl; var M: TMsg; var Rslt: Integer ): Boolean;
42498 begin
42499 if M.message = WM_CHAR then
42500 begin
42501 if M.wParam = 9 then
42502 begin
42503 //M.wParam := 0;
42504 Sender.ReplaceSelection( #9, TRUE );
42505 end;
42506 end;
42507 Result := FALSE;
42508 end;
42510 //[function TControl.EditTabChar]
42511 function TControl.EditTabChar: PControl;
42512 begin
42513 AttachProc( WndProcTabChar );
42514 Result := @Self;
42515 end;
42517 {$IFDEF ASM_VERSION}
42518 //[function TControl.Add]
42519 function TControl.Add(const S: String): Integer;
42521 PUSH EBX
42522 MOV EBX, EAX // EBX = @Self
42524 MOVZX ECX, [EBX].fCommandActions.aAddItem // ECX = aAddItem
42525 JECXZ @@chk_addtext
42527 CALL EDX2PChar
42528 PUSH EDX
42529 PUSH 0
42530 PUSH ECX
42531 PUSH EBX
42532 CALL Perform
42533 PUSH EAX
42535 MOV EAX, EBX
42536 CALL TControl.GetItemsCount
42537 XCHG EAX, ECX
42538 LOOP @@ret_EAX
42540 XCHG EAX, EBX
42541 INC ECX
42542 XOR EDX, EDX
42543 CALL TControl.SetItemSelected
42544 @@ret_EAX:
42545 POP EAX
42546 JMP @@exit
42548 @@chk_addtext:
42549 MOV ECX, [EBX].fCommandActions.aAddText
42550 JECXZ @@add_text_simple
42552 CALL ECX
42553 JMP @@exit_0
42555 @@add_text_simple:
42556 PUSH EDX
42557 PUSH 0
42558 MOV EDX, ESP
42559 CALL GetCaption
42560 POP EAX
42561 POP EDX
42562 PUSH EAX
42563 MOV EAX, ESP
42564 CALL System.@LStrCat
42565 MOV EAX, EBX
42566 POP EDX
42567 PUSH EDX
42568 CALL SetCaption
42569 CALL RemoveStr
42570 @@exit_0:
42571 XOR EAX, EAX
42572 @@exit:
42573 POP EBX
42574 end;
42575 {$ELSE ASM_VERSION} //Pascal
42576 function TControl.Add(const S: String): Integer;
42577 begin
42578 if fCommandActions.aAddItem <> 0 then
42579 begin
42580 Result := Perform( fCommandActions.aAddItem, 0, Integer( PChar( S ) ) );
42581 if Count = 1 then
42582 ItemSelected[ 0 ] := True;
42584 else
42585 begin
42586 if assigned( fCommandActions.aAddText ) then
42587 fCommandActions.aAddText( @Self, S )
42588 else
42589 Text := Text + S;
42590 Result := 0;
42591 end;
42592 end;
42593 {$ENDIF ASM_VERSION}
42595 {$IFDEF ASM_VERSION}
42596 //[procedure TControl.Delete]
42597 procedure TControl.Delete(Idx: Integer);
42599 MOVZX ECX, [EAX].fCommandActions.aDeleteItem
42600 JECXZ @@exit
42602 PUSH 0
42603 PUSH EDX
42604 PUSH ECX
42605 PUSH EAX
42606 CALL Perform
42607 @@exit:
42608 end;
42609 {$ELSE ASM_VERSION} //Pascal
42610 procedure TControl.Delete(Idx: Integer);
42611 begin
42612 if fCommandActions.aDeleteItem <> 0 then
42613 Perform( fCommandActions.aDeleteItem, Idx, 0 );
42614 end;
42615 {$ENDIF ASM_VERSION}
42617 {$IFDEF ASM_VERSION}
42618 //[function TControl.Insert]
42619 function TControl.Insert(Idx: Integer; const S: String): Integer;
42621 CALL ECX2PChar
42622 PUSH ECX
42623 MOVZX ECX, [EAX].fCommandActions.aInsertItem
42624 JECXZ @@exit_1
42626 PUSH EDX
42627 PUSH ECX
42628 PUSH EAX
42629 CALL Perform
42632 @@exit_1:OR EAX, -1
42633 POP ECX
42634 end;
42635 {$ELSE ASM_VERSION} //Pascal
42636 function TControl.Insert(Idx: Integer; const S: String): Integer;
42637 begin
42638 if fCommandActions.aInsertItem <> 0 then
42639 Result := Perform( fCommandActions.aInsertItem, Idx, Integer( PChar( S ) ) )
42640 else
42641 Result := -1;
42642 end;
42643 {$ENDIF ASM_VERSION}
42645 {$IFDEF ASM_VERSION}
42646 //[function TControl.GetItemSelected]
42647 function TControl.GetItemSelected(ItemIdx: Integer): Boolean;
42649 MOVZX ECX, [EAX].fCommandActions.aGetSelected
42650 JECXZ @@check_range
42652 PUSH 0
42653 PUSH EDX
42654 PUSH ECX
42655 PUSH EAX
42656 CALL Perform
42657 TEST EAX, EAX
42658 SETG AL
42661 @@check_range:
42662 MOVZX ECX, [EAX].fCommandActions.aGetSelRange
42663 JECXZ @@check_ex
42665 PUSH EDX
42666 PUSH 0
42667 PUSH 0
42668 PUSH ECX
42669 PUSH EAX
42670 CALL Perform
42671 POP EDX
42672 TEST EAX, EAX
42673 JL @@ret_false
42675 CMP DX, AX
42676 JL @@ret_false
42678 SHR EAX, 16
42679 SUB EDX, EAX
42680 SETL AL
42683 @@check_ex:
42684 MOVZX ECX, [EAX].fCommandActions.aExGetSelRange
42685 JECXZ @@ret_false
42686 PUSH EDX
42687 PUSH EDX
42688 PUSH EDX
42689 PUSH ESP
42690 PUSH 0
42691 PUSH ECX
42692 PUSH EAX
42693 CALL Perform
42694 POP ECX
42695 POP EDX
42696 POP EAX
42698 SUB EAX, EDX
42699 CMP EAX, ECX
42700 SETB AL
42703 @@ret_false:
42704 XOR EAX, EAX
42705 end;
42706 {$ELSE ASM_VERSION} //Pascal
42707 function TControl.GetItemSelected(ItemIdx: Integer): Boolean;
42708 var SR: TCharRange;
42709 begin
42710 Result := False;
42711 if fCommandActions.aGetSelected <> 0 then
42712 Result := 0 < Perform( fCommandActions.aGetSelected, ItemIdx, 0 )
42713 else if fCommandActions.aGetSelRange <> 0 then
42714 begin
42715 Perform( fCommandActions.aGetSelRange, Integer( @SR.cpMin ), Integer( @SR.cpMax ) );
42716 Result := (SR.cpMin <= ItemIdx) and (ItemIdx < SR.cpMax);
42718 else if fCommandActions.aExGetSelRange <> 0 then
42719 begin
42720 Perform( fCommandActions.aExGetSelRange, 0, Integer( @SR ) );
42721 Result := (SR.cpMin <= ItemIdx) and (ItemIdx < SR.cpMax);
42722 end;
42723 end;
42724 {$ENDIF ASM_VERSION}
42726 {$IFDEF ASM_VERSION}
42727 //[procedure TControl.SetItemSelected]
42728 procedure TControl.SetItemSelected(ItemIdx: Integer; const Value: Boolean);
42730 PUSH EDX
42731 PUSH ECX
42732 MOVZX ECX, [EAX].fCommandActions.aSetSelected
42733 JECXZ @@chk_aSetCurrent
42735 @@0:
42736 PUSH ECX
42737 PUSH EAX
42738 CALL Perform
42741 @@chk_aSetCurrent:
42742 POP ECX
42743 MOVZX ECX, [EAX].fCommandActions.aSetCurrent
42744 JECXZ @@chk_aSetSelRange
42746 POP EDX
42747 PUSH 0
42748 JMP @@3
42750 @@chk_aSetSelRange:
42751 MOVZX ECX, [EAX].fCommandActions.aSetSelRange
42752 JECXZ @@chk_aExSetSelRange
42753 @@3:
42754 PUSH EDX
42755 JMP @@0
42757 @@else: MOV [EAX].FCurIndex, EDX
42758 CALL Invalidate
42759 JMP @@exit
42761 @@chk_aExSetSelRange:
42762 MOVZX ECX, [EAX].fCommandActions.aExSetSelRange
42763 JECXZ @@else
42765 PUSH EDX
42766 PUSH ESP
42767 PUSH 0
42768 PUSH ECX
42769 PUSH EAX
42770 CALL Perform
42771 POP ECX
42773 @@exit:
42774 POP ECX
42775 end;
42776 {$ELSE ASM_VERSION} //Pascal
42777 procedure TControl.SetItemSelected(ItemIdx: Integer; const Value: Boolean);
42778 var SR: TCharRange;
42779 begin
42780 if fCommandActions.aSetSelected <> 0 then
42781 Perform( fCommandActions.aSetSelected, Integer( Value ), ItemIdx )
42782 else
42783 if fCommandActions.aSetCurrent <> 0 then
42784 Perform( fCommandActions.aSetCurrent, ItemIdx, 0 )
42785 else
42786 if fCommandActions.aSetSelRange <> 0 then
42787 Perform( fCommandActions.aSetSelRange, ItemIdx, ItemIdx )
42788 else
42789 if fCommandActions.aExSetSelRange <> 0 then
42790 begin
42791 SR.cpMin := ItemIdx;
42792 SR.cpMax := ItemIdx;
42793 Perform( fCommandActions.aExSetSelRange, 0, Integer( @SR ) );
42795 else
42796 begin // for ImageShow: set the index and invalidate the control
42797 FCurIndex := ItemIdx;
42798 Invalidate;
42799 end;
42800 end;
42801 {$ENDIF ASM_VERSION}
42803 {$IFDEF ASM_VERSION}
42804 //[procedure TControl.SetCtl3D]
42805 procedure TControl.SetCtl3D(const Value: Boolean);
42807 MOV [EAX].fCtl3Dchild, DL
42808 CMP [EAX].fCtl3D, DL
42809 JE @@exit
42810 MOV [EAX].fCtl3D, DL
42811 PUSHAD
42812 CALL UpdateWndStyles
42813 POPAD
42814 MOV ECX, [EAX].fExStyle
42815 DEC DL
42816 MOV EDX, [EAX].fStyle
42817 JNZ @@1
42818 AND EDX, not WS_BORDER
42819 OR CH, WS_EX_CLIENTEDGE shr 8
42820 JMP @@2
42821 @@1:
42822 OR EDX, WS_BORDER
42823 AND CH, not(WS_EX_CLIENTEDGE shr 8)
42824 @@2:
42825 PUSH ECX
42826 PUSH EAX
42827 CALL SetStyle
42828 POP EAX
42829 POP EDX
42830 JMP SetExStyle
42831 @@exit:
42832 end;
42833 {$ELSE ASM_VERSION} //Pascal
42834 procedure TControl.SetCtl3D(const Value: Boolean);
42835 begin
42836 fCtl3Dchild := Value;
42837 if fCtl3D = Value then Exit;
42838 fCtl3D := Value;
42839 UpdateWndStyles;
42840 if Value then
42841 begin
42842 ExStyle := fExStyle or WS_EX_CLIENTEDGE;
42843 Style := fStyle and not WS_BORDER;
42845 else
42846 begin
42847 ExStyle := fExStyle and not WS_EX_CLIENTEDGE;
42848 Style := fStyle or WS_BORDER;
42849 end;
42850 end;
42851 {$ENDIF ASM_VERSION}
42853 {$IFDEF ASM_VERSION}
42854 //[function TControl.Shift]
42855 function TControl.Shift(dX, dY: Integer): PControl;
42857 PUSHAD
42858 ADD EDX, [EAX].fBoundsRect.TRect.Left
42859 CALL SetLeft
42860 POPAD
42861 PUSH EAX
42862 MOV EDX, [EAX].fBoundsRect.TRect.Top
42863 ADD EDX, ECX
42864 CALL SetTop
42865 POP EAX
42866 end;
42867 {$ELSE ASM_VERSION} //Pascal
42868 function TControl.Shift(dX, dY: Integer): PControl;
42869 begin
42870 Left := fBoundsRect.Left + dX;
42871 Top := fBoundsRect.Top + dY;
42872 Result := @Self;
42873 end;
42874 {$ENDIF ASM_VERSION}
42876 //[procedure SetKeyEvent]
42877 procedure SetKeyEvent( Self_: PControl );
42878 begin
42879 Self_.fWndProcKeybd := WndProcKeybd;
42880 //Self_.AttachProc( WndProcKeyBd );
42881 end;
42883 //[procedure TControl.SetOnChar]
42884 procedure TControl.SetOnChar(const Value: TOnChar);
42885 begin
42886 fOnChar := Value;
42887 SetKeyEvent( @Self );
42888 end;
42890 //[procedure TControl.SetOnKeyDown]
42891 procedure TControl.SetOnKeyDown(const Value: TOnKey);
42892 begin
42893 fOnKeyDown := Value;
42894 SetKeyEvent( @Self );
42895 end;
42897 //[procedure TControl.SetOnKeyUp]
42898 procedure TControl.SetOnKeyUp(const Value: TOnKey);
42899 begin
42900 fOnKeyUp := Value;
42901 SetKeyEvent( @Self );
42902 end;
42904 //[FUNCTION CollectTabControls]
42905 {$IFDEF ASM_VERSION}
42906 function CollectTabControls( Form: PControl ): PList;
42908 PUSH EDI
42909 PUSH EAX
42910 CALL NewList
42911 XCHG EDI, EAX
42912 POP EAX
42913 CALL @@collecttab
42914 XCHG EAX, EDI
42915 POP EDI
42917 @@collecttab:
42918 { <- EDI = Result:PList
42919 EAX = Form (or Control)
42921 PUSH ESI
42922 PUSH EBX
42923 MOV EDX, [EAX].TControl.fChildren
42924 MOV ECX, [EDX].TList.fCount
42925 MOV ESI, [EDX].TList.fItems
42926 JECXZ @@e_loop
42927 @@loo: PUSH ECX
42928 LODSD
42930 PUSH EAX
42932 TEST byte ptr [EAX].TControl.fStyle+2, WS_TABSTOP shr 16
42933 JZ @@call_recur
42935 MOV DL, [EAX].TControl.fTabStop
42936 AND DL, [EAX].TControl.fEnabled
42937 JZ @@call_recur
42939 CALL TControl.GetToBeVisible
42940 TEST AL, AL
42941 POP EAX
42942 JZ @@next
42943 PUSH EAX
42945 XCHG EDX, EAX
42946 PUSH ESI
42947 MOV ECX, [EDI].TList.fCount
42948 MOV ESI, [EDI].TList.fItems
42949 XOR EBX, EBX
42950 JECXZ @@e_loo2
42951 @@loo2: LODSD
42952 MOV EAX, [EAX].TControl.fTabOrder
42953 CMP EAX, [EDX].TControl.fTabOrder
42954 JLE @@next2
42955 POP ESI
42956 MOV ECX, EDX
42957 MOV EDX, EBX
42958 MOV EAX, EDI
42959 CALL TList.Insert
42960 JMP @@call_recur
42962 @@next2: INC EBX
42963 LOOP @@loo2
42964 @@e_loo2:
42965 POP ESI
42966 MOV EAX, EDI
42967 CALL TList.Add
42969 @@call_recur:
42970 POP EAX
42971 MOVZX ECX, [EAX].TControl.fEnabled
42972 JECXZ @@next
42973 CALL @@collecttab
42975 @@next: POP ECX
42976 LOOP @@loo
42978 @@e_loop:
42979 POP EBX
42980 POP ESI
42981 end;
42982 {$ELSE ASM_VERSION} //Pascal
42983 function CollectTabControls( Form: PControl ): PList;
42984 var R: PList;
42985 procedure CollectTab( P: PControl );
42986 var I, J: Integer;
42987 C, D: PControl;
42988 begin
42989 for I := 0 to P.fChildren.fCount - 1 do
42990 begin
42991 C := P.fChildren.fItems[ I ];
42992 if C.fTabstop and C.fEnabled and C.ToBeVisible and
42993 (C.fStyle and WS_TABSTOP <> 0) then
42994 begin
42995 D := nil;
42996 for J := 0 to R.fCount - 1 do
42997 begin
42998 D := R.fItems[ J ];
42999 if D.fTabOrder > C.fTabOrder then
43000 begin
43001 R.Insert( J, C );
43002 break;
43004 else
43005 D := nil;
43006 end;
43007 if D = nil then
43008 R.Add( C );
43009 end;
43010 if C.fEnabled then
43011 CollectTab( C );
43012 end;
43013 end;
43014 begin
43015 R := NewList;
43016 CollectTab( Form );
43017 Result := R;
43018 end;
43019 {$ENDIF ASM_VERSION}
43020 //[END CollectTabControls]
43022 //[PROCEDURE Tabulate2Next]
43023 {$IFDEF ASM_VERSION}
43024 procedure Tabulate2Next( Form: PControl; Dir: Integer );
43026 PUSHAD
43027 PUSH EAX // save Form
43028 MOV EBX, EAX
43029 MOV EBP, EDX // EBP = Dir (direction <0 or >0)
43030 CALL CollectTabControls
43031 XCHG EDI, EAX // EDI = CL (list of controls)
43033 MOV ECX, [EBX].TControl.fCurrentControl // C := Form.fCurrentControl
43034 XOR EBX, EBX // I = 0
43035 JECXZ @@1
43036 MOV EBX, [ECX].TControl.fTabOrder // I = C.fTabOrder
43037 @@1:
43038 MOV ECX, [EDI].TList.fCount
43039 MOV ESI, [EDI].TList.fItems
43040 XOR EDX, EDX
43041 PUSH EDX // Ctrl1 = nil
43042 PUSH EDX // Ctrl2 = nil
43043 //JECXZ @@e_loop
43044 TEST ECX, ECX
43045 JZ @@e_loop
43047 @@loop: PUSH ECX
43048 LODSD
43049 CMP [EAX].TControl.fTabOrder, EBX
43050 JZ @@next
43052 MOV ECX, [ESP+8] // ECX = Ctrl1
43053 JECXZ @@c1nil
43054 MOV ECX, [ECX].TControl.fTabOrder // ECX = Ctrl1.fTabOrder
43055 TEST EBP, EBP
43056 JGE @@c1ge
43058 CMP [EAX].TControl.fTabOrder, EBX
43059 JGE @@2
43060 CMP [EAX].TControl.fTabOrder, ECX
43061 JLE @@2
43063 @@c1new:
43064 MOV [ESP+8], EAX // Ctrl1 := C
43065 JMP @@2
43067 @@c1ge: CMP [EAX].TControl.fTabOrder, EBX
43068 JLE @@2
43069 CMP [EAX].TControl.fTabOrder, ECX
43070 JL @@c1new
43071 JMP @@2
43073 @@c1nil:
43074 TEST EBP, EBP
43075 JL @@c1nil_dirL
43076 CMP [EAX].TControl.fTabOrder, EBX
43077 JG @@c1new
43078 JMP @@2
43080 @@c1nil_dirL:
43081 CMP [EAX].TControl.fTabOrder, EBX
43082 JL @@c1new
43084 @@2:
43085 MOV ECX, [ESP+4] // ECX = Ctrl2
43086 JECXZ @@c2new
43087 MOV ECX, [ECX].TControl.fTabOrder
43089 TEST EBP, EBP
43090 JL @@c2dirL
43091 CMP [EAX].TControl.fTabOrder, ECX
43092 JGE @@next
43093 JMP @@c2new
43095 @@c2dirL:
43096 CMP [EAX].TControl.fTabOrder, ECX
43097 JLE @@next
43098 @@c2new:
43099 MOV [ESP+4], EAX
43101 @@next: POP ECX
43102 DEC ECX
43103 JNZ @@loop
43104 //LOOP @@loop
43105 @@e_loop:
43107 POP EDX // Ctrl2
43108 POP ECX // Ctrl1
43109 INC ECX
43110 LOOP @@3
43111 MOV ECX, EDX
43112 @@3:
43113 POP EBX // EBX = Form
43114 JECXZ @@exit
43116 XCHG EAX, ECX
43117 MOV ECX, [EAX].TControl.fHandle
43118 JECXZ @@no_handle
43120 INC [EAX].TControl.fClickDisabled
43121 PUSH EAX
43122 PUSH ECX
43123 CALL Windows.SetFocus
43124 POP EAX
43125 DEC [EAX].TControl.fClickDisabled
43127 @@no_handle:
43128 MOV [EBX].TControl.fCurrentControl, EAX
43130 @@exit:
43131 XCHG EAX, EDI
43132 CALL TObj.Free
43133 POPAD
43134 end;
43135 {$ELSE ASM_VERSION} //Pascal
43136 procedure Tabulate2Next( Form: PControl; Dir: Integer );
43137 var CL : PList;
43138 I, J : Integer;
43139 Ctrl1, Ctrl2, C : PControl;
43140 begin
43141 CL := CollectTabControls( Form );
43143 I := 0;
43144 C := Form.fCurrentControl;
43145 if C <> nil then
43146 I := C.fTabOrder;
43147 Ctrl2 := nil;
43148 Ctrl1 := nil;
43149 for J := 0 to CL.fCount - 1 do
43150 begin
43151 C := CL.fItems[ J ];
43152 if C.fTabOrder = I then continue;
43153 if (Ctrl1 = nil)
43154 and ( (Dir >= 0) and (C.fTabOrder > I)
43155 or (Dir < 0) and (C.fTabOrder < I) )
43156 or (Dir >= 0)
43157 and (C.fTabOrder > I) and (C.fTabOrder < Ctrl1.fTabOrder)
43158 or (Dir < 0)
43159 and (C.fTabOrder < I) and (C.fTabOrder > Ctrl1.fTabOrder)
43160 then Ctrl1 := C;
43161 if (Ctrl2 = nil)
43162 or (Dir >= 0) and (C.fTabOrder < Ctrl2.fTabOrder)
43163 or (Dir < 0) and (C.fTabOrder > Ctrl2.fTabOrder)
43164 then Ctrl2 := C;
43165 end;
43166 if Ctrl1 = nil then
43167 Ctrl1 := Ctrl2;
43168 if Ctrl1 <> nil then
43169 begin
43170 if Ctrl1.fHandle <> 0 then
43171 begin
43172 Inc( Ctrl1.fClickDisabled );
43173 SetFocus( Ctrl1.fHandle );
43174 Dec( Ctrl1.fClickDisabled );
43175 end;
43176 Form.fCurrentControl := Ctrl1;
43177 end;
43178 CL.Free;
43179 end;
43180 {$ENDIF ASM_VERSION}
43181 //[END Tabulate2Next]
43183 //[FUNCTION Tabulate2Control]
43184 {$IFDEF ASM_VERSION}
43185 function Tabulate2Control( Self_: PControl; Key: DWORD; checkOnly: Boolean ): Boolean;
43186 const tk_Tab = 1;
43187 tk_LR = 2;
43188 tk_UD = 4;
43189 tk_PuPd= 8;
43191 PUSH ESI
43192 MOV ESI, offset[@@data]
43193 PUSH EAX
43194 MOV AH, 9
43195 @@loop:
43196 LODSB
43197 CMP DL, AL
43198 JE @@1
43199 LODSB
43200 CMP DL, AL
43201 JE @@2
43202 ADD AH, AH
43203 JNB @@loop
43204 POP EAX
43205 @@exit0:
43206 XOR EAX, EAX
43207 JMP @@exit
43209 @@data:
43210 DB -1, VK_TAB, VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN, VK_PRIOR, VK_NEXT
43212 @@1:
43213 OR EDX, -1
43214 JMP @@3
43215 @@2:
43216 XOR EDX, EDX
43217 TEST AH, 1
43218 JZ @@3
43220 PUSH ECX
43221 PUSH EAX
43222 PUSH VK_SHIFT
43223 CALL GetAsyncKeyState
43225 POP EAX
43226 POP ECX
43227 @@3:
43228 POP ESI
43229 //////////////////////////////////////////////////
43230 MOV AL, AH
43231 {$IFDEF PARANOIA}
43232 DB $24, 1
43233 {$ELSE}
43234 AND AL, 1
43235 {$ENDIF}
43236 TEST byte ptr [ESI].TControl.fLookTabKeys, AL
43237 //////////////////////////////////////////////////
43238 JZ @@exit0
43240 TEST CL, CL
43241 JNZ @@exit
43243 PUSH EDX
43244 MOV EAX, ESI
43245 CALL TControl.ParentForm
43246 POP EDX
43247 CALL Tabulate2Next
43248 @@exit:
43249 POP ESI
43250 end;
43251 {$ELSE ASM_VERSION} //Pascal
43252 function Tabulate2Control( Self_: PControl; Key: DWORD; checkOnly: Boolean ): Boolean;
43253 var Form: PControl;
43254 begin
43255 Result := False;
43256 case Key of
43257 VK_TAB: if not (tkTab in Self_.fLookTabKeys) then exit;
43258 VK_LEFT, VK_RIGHT: if not (tkLeftRight in Self_.fLookTabKeys) then exit;
43259 VK_UP, VK_DOWN: if not (tkUpDown in Self_.fLookTabKeys) then exit;
43260 VK_NEXT, VK_PRIOR: if not (tkPageUpPageDn in Self_.fLookTabKeys) then exit;
43261 else Exit;
43262 end;
43264 Result := True;
43265 if checkOnly then Exit;
43267 Form := Self_.ParentForm;
43268 case Key of
43269 VK_TAB:
43270 if GetKeyState( VK_SHIFT ) < 0 then
43271 Tabulate2Next( Form, -1 )
43272 else
43273 Tabulate2Next( Form, 1 );
43274 VK_RIGHT, VK_DOWN, VK_NEXT: Tabulate2Next( Form, 1 );
43275 VK_LEFT, VK_UP, VK_PRIOR: Tabulate2Next( Form, -1 );
43276 end;
43277 end;
43278 {$ENDIF ASM_VERSION}
43279 //[END Tabulate2Control]
43281 //[FUNCTION Tabulate2ControlEx]
43282 {$IFDEF ASM_VERSION}
43283 function Tabulate2ControlEx( Self_: PControl; Key: DWORD; checkOnly: Boolean ): Boolean;
43285 PUSH EDI
43286 MOVZX EDI, CL
43287 TEST byte ptr [EAX].TControl.fLookTabKeys, 1
43288 JZ @@1
43289 @@0:
43290 MOV ECX, EDX
43291 AND CL, 7Fh
43292 CMP CL, VK_TAB
43293 JNE @@1
43295 PUSH EDX
43296 CALL TControl.ParentForm
43297 POP EDX
43298 MOVSX EDX, DL
43299 TEST EDX, EDX
43300 JS @@tab
43302 PUSH EAX
43304 PUSH VK_SHIFT
43305 CALL GetAsyncKeyState
43306 SAR EAX, 31
43307 {$IFDEF PARANOIA}
43308 DB $0C, $01
43309 {$ELSE}
43310 OR AL, 1
43311 {$ENDIF}
43312 MOV EDX, EAX
43314 POP EAX
43315 @@tab:
43316 TEST EDI, EDI
43317 POP EDI
43318 JNZ @@no_tab
43319 CALL Tabulate2Next
43320 @@no_tab:
43321 MOV AL, 1
43324 @@data: DB VK_LEFT, VK_LEFT
43325 DD offset[@@left]
43326 DB VK_UP, 2
43327 DB VK_RIGHT, VK_RIGHT
43328 DD offset[@@right]
43329 DB VK_DOWN, 2
43330 DB VK_UP, VK_PRIOR
43331 DD offset[@@up]
43332 DB VK_TAB or 80h, $C
43333 DB VK_DOWN, VK_NEXT
43334 DD offset[@@down]
43335 DB VK_TAB, $C
43337 @@1:
43339 EAX <- Self_:PControl
43340 DL <- Key
43342 PUSH ESI
43343 MOV ESI, offset[@@data]-6
43344 MOV DH, 9
43345 PUSH EAX
43346 @@loop:
43347 ADD DH, DH
43348 JNB @@l1
43349 JMP @@abort
43350 @@fault1:
43351 POP EDI
43352 POPAD
43353 PUSH EAX
43354 @@abort:
43355 POP EAX
43356 @@abort1:
43357 POP ESI
43358 POP EDI
43359 XOR EAX, EAX
43362 @@right:
43363 MOV EAX, [ESP].TRect.Left
43364 SUB EAX, [ESP+16].TRect.Left
43365 @@left_right:
43366 JL @@next1
43367 MOV EDX, [ESP].TRect.Bottom
43368 SUB EDX, [ESP+16].TRect.Top
43369 JL @@next1
43370 MOV EDX, [ESP].TRect.Top
43371 SUB EDX, [ESP+16].TRect.Bottom
43372 JGE @@next1
43373 @@chk_dist:
43374 CMP EAX, EDI
43375 JA @@next1
43376 MOV EDI, EAX
43377 MOV EAX, [EBX+ECX*4-4]
43378 MOV [ESP+36], EAX // Found = Ctrl
43379 JMP @@next1
43381 @@l1:
43382 LODSD
43383 LODSW
43384 LODSW
43385 CMP AL, DL
43386 JE @@2
43387 CMP AH, DL
43388 JNE @@loop
43390 @@2:
43391 PUSH ESI
43392 LODSD
43393 LODSW
43394 POP ESI
43395 XCHG EDX, EAX
43396 POP EAX
43397 TEST [EAX].TControl.fLookTabKeys, DH
43398 JZ @@abort1
43400 PUSHAD
43401 PUSH EDI
43402 CALL TControl.ParentForm
43403 MOV ECX, [EAX].TControl.fCurrentControl
43404 JECXZ @@fault1
43405 MOV EBP, ECX // EBP = CurCtrl
43407 PUSH EAX // save Form
43408 MOV EBX, EAX
43409 CALL CollectTabControls
43410 PUSH 0 // save Found = nil
43411 PUSH EAX // save CollectedList
43412 MOV EDI, EAX
43414 MOV EBX, [EDI].TList.fItems
43415 ADD ESP, -16
43416 PUSH ESP
43417 PUSH [EBP].TControl.fHandle
43418 CALL GetWindowRect
43420 MOV ECX, [EDI].TList.fCount
43421 OR EDI, -1 // EDI = minDist
43422 @@loop1:
43423 MOV EAX, [EBX+ECX*4-4]
43424 CMP EAX, EBP
43425 JE @@next
43427 MOV DL, [EAX].TControl.fEnabled
43428 AND DL, [EAX].TControl.fTabstop
43429 JZ @@next
43431 ADD ESP, -16
43432 MOV EDX, ESP
43433 PUSH ECX
43435 //CALL TControl.ControlRect
43436 PUSH EDX
43437 PUSH [EAX].TControl.fHandle
43438 CALL GetWindowRect
43440 POP ECX
43441 JMP dword ptr [ESI]
43443 @@left:
43444 MOV EAX, [ESP+16].TRect.Left
43445 SUB EAX, [ESP].TRect.Left
43446 JMP @@left_right
43448 @@not_found:
43449 POP EDI
43450 POPAD
43451 MOV DL, [ESI+4]
43452 POP ESI
43453 JMP @@0
43455 @@up:
43456 MOV EAX, [ESP+16].TRect.Top
43457 SUB EAX, [ESP].TRect.Top
43458 JMP @@up_down
43459 @@down:
43460 MOV EAX, [ESP].TRect.Top
43461 SUB EAX, [ESP+16].TRect.Top
43462 @@up_down:
43463 JL @@next1
43464 MOV EDX, [ESP].TRect.Right
43465 SUB EDX, [ESP+16].TRect.Left
43466 JL @@next1
43467 MOV EDX, [ESP].TRect.Left
43468 SUB EDX, [ESP+16].TRect.Right
43469 JL @@chk_dist
43471 @@next1:
43472 ADD ESP, 16
43473 @@next:
43474 LOOP @@loop1
43475 ADD ESP, 16
43476 POP EAX // pop CollectedList
43477 CALL TObj.Free
43478 POP ECX // pop Found
43479 POP EAX // pop Form
43480 JECXZ @@not_found
43482 POP EDI
43483 TEST EDI, EDI
43484 JNZ @@no_go
43486 MOV [EAX].TControl.fCurrentControl, ECX
43487 INC [ECX].TControl.fClickDisabled
43488 PUSH ECX
43489 MOV ECX, [ECX].TControl.fHandle
43490 JECXZ @@4
43491 PUSH ECX
43492 CALL Windows.SetFocus
43493 @@4: POP ECX
43494 DEC [ECX].TControl.fClickDisabled
43495 @@no_go:
43496 POPAD
43497 POP ESI
43498 POP EDI
43499 MOV AL, 1 // Result = True
43500 end;
43501 {$ELSE ASM_VERSION} //Pascal
43502 function Tabulate2ControlEx( Self_: PControl; Key: DWORD; checkOnly: Boolean ): Boolean;
43503 label search_tabcontrol;
43504 var Form: PControl;
43505 CL : PList;
43506 I : Integer;
43507 CurCtrl, Ctrl, Found : PControl;
43508 MinDist, Dist: Integer;
43509 R, R1 : TRect;
43510 begin
43511 Result := False;
43512 case Key of
43513 VK_TAB: if not (tkTab in Self_.fLookTabKeys) then exit;
43514 VK_LEFT, VK_RIGHT: if not (tkLeftRight in Self_.fLookTabKeys) then exit;
43515 VK_UP, VK_DOWN: if not (tkUpDown in Self_.fLookTabKeys) then exit;
43516 VK_NEXT, VK_PRIOR: if not (tkPageUpPageDn in Self_.fLookTabKeys) then exit;
43517 else exit;
43518 end;
43520 Result := True;
43521 if checkOnly then Exit;
43523 Form := Self_.ParentForm;
43524 if Key = VK_TAB then
43525 if GetKeyState( VK_SHIFT ) < 0 then
43526 Tabulate2Next( Form, -1 )
43527 else
43528 Tabulate2Next( Form, 1 )
43529 else
43530 begin
43531 CL := CollectTabControls( Form );
43532 I := CL.IndexOf( Form.fCurrentControl );
43533 Found := nil;
43534 if I >= 0 then
43535 begin
43536 CurCtrl := CL.fItems[ I ];
43537 //R := CurCtrl.ControlRect;
43538 GetWindowRect( CurCtrl.Handle, R );
43539 search_tabcontrol:
43540 MinDist := MaxInt;
43541 for I := CL.fCount - 1 downto 0 do
43542 begin
43543 Ctrl := CL.fItems[ I ];
43544 if Ctrl = CurCtrl then continue;
43545 if not (Ctrl.fEnabled and Ctrl.fTabstop) then continue;
43546 //R1 := Ctrl.ControlRect;
43547 GetWindowRect( Ctrl.Handle, R1 );
43548 Dist := MaxInt;
43549 case Key of
43550 VK_LEFT:
43551 begin
43552 if (R1.Bottom < R.Top)
43553 or (R1.Top >= R.Bottom)
43554 or (R1.Left > R.Left) then continue;
43555 Dist := R.Left - R1.Left;
43556 end;
43557 VK_RIGHT:
43558 begin
43559 if (R1.Bottom < R.Top)
43560 or (R1.Top >= R.Bottom)
43561 or (R1.Left < R.Left) then continue;
43562 Dist := R1.Left - R.Left;
43563 end;
43564 VK_UP, VK_PRIOR:
43565 begin
43566 if (R1.Right < R.Left)
43567 or (R1.Left >= R.Right)
43568 or (R1.Top > R.Top) then continue;
43569 Dist := R.Top - R1.Top;
43570 end;
43571 VK_DOWN, VK_NEXT:
43572 begin
43573 if (R1.Right < R.Left)
43574 or (R1.Left >= R.Right)
43575 or (R1.Top < R.Bottom) then continue;
43576 Dist := R1.Top - R.Top;
43577 end;
43578 end;
43579 if Dist < MinDist then
43580 begin
43581 Found := Ctrl;
43582 MinDist := Dist;
43583 end;
43584 end;
43585 if Found = nil then
43586 begin
43587 case Key of
43588 VK_LEFT:
43589 begin
43590 Key := VK_UP; goto search_tabcontrol;
43591 end;
43592 VK_RIGHT:
43593 begin
43594 Key := VK_DOWN; goto search_tabcontrol;
43595 end;
43596 VK_UP, VK_PRIOR:
43597 Tabulate2Next( Form, -1 );
43598 VK_DOWN, VK_NEXT:
43599 Tabulate2Next( Form, 1 );
43600 end;
43602 else
43603 begin
43604 if Found.fHandle <> 0 then
43605 begin
43606 Inc( Found.fClickDisabled );
43607 SetFocus( Found.fHandle );
43608 Dec( Found.fClickDisabled );
43609 end;
43610 Form.fCurrentControl := Found;
43611 end;
43612 end;
43613 CL.Free;
43614 end;
43615 end;
43616 {$ENDIF ASM_VERSION}
43617 //[END Tabulate2ControlEx]
43619 {$IFDEF ASM_VERSION}
43620 //[function TControl.Tabulate]
43621 function TControl.Tabulate: PControl;
43623 PUSH EAX
43624 CALL ParentForm
43625 TEST EAX, EAX
43626 JZ @@exit
43627 MOV [EAX].fGotoControl, offset[Tabulate2Control]
43628 @@exit: POP EAX
43629 end;
43630 {$ELSE ASM_VERSION} //Pascal
43631 function TControl.Tabulate: PControl;
43632 var F : PControl;
43633 begin
43634 Result := @Self;
43635 F := ParentForm;
43636 if F = nil then Exit;
43637 F.fGotoControl := Tabulate2Control;
43638 end;
43639 {$ENDIF ASM_VERSION}
43641 {$IFDEF ASM_VERSION}
43642 //[function TControl.TabulateEx]
43643 function TControl.TabulateEx: PControl;
43645 PUSH EAX
43646 CALL ParentForm
43647 TEST EAX, EAX
43648 JZ @@exit
43649 MOV [EAX].fGotoControl, offset[Tabulate2ControlEx]
43650 @@exit: POP EAX
43651 end;
43652 {$ELSE ASM_VERSION} //Pascal
43653 function TControl.TabulateEx: PControl;
43654 var F : PControl;
43655 begin
43656 Result := @Self;
43657 F := ParentForm;
43658 if F = nil then Exit;
43659 F.fGotoControl := Tabulate2ControlEx;
43660 end;
43661 {$ENDIF ASM_VERSION}
43664 //[procedure TControl.GotoControl]
43665 procedure TControl.GotoControl(Key: DWORD);
43666 var Form: PControl;
43667 begin
43668 Form := ParentForm;
43669 if Form <> nil then
43670 if assigned( Form.fGotoControl ) then
43671 Form.fGotoControl( Form.fCurrentControl, Key, false );
43672 end;
43674 {$IFDEF ASM_VERSION}
43675 //[function TControl.GetCurIndex]
43676 function TControl.GetCurIndex: Integer;
43678 PUSH EBX
43679 XCHG EBX, EAX
43680 MOV EAX, [EBX].fCurIndex
43681 MOVZX ECX, [EBX].fCommandActions.aGetCurrent
43682 JECXZ @@exit
43683 XOR EAX, EAX
43685 CMP CX, LVM_GETNEXTITEM
43686 JNE @@0
43687 INC EAX
43688 INC EAX
43689 JMP @@1
43690 @@0:
43691 CMP CL, EM_LINEINDEX and $FF
43692 JNZ @@2
43693 @@1:
43694 DEC EDX
43695 @@2:
43696 PUSH EAX
43697 PUSH EDX
43698 PUSH ECX
43699 PUSH EBX
43700 CALL Perform
43702 @@exit: POP EBX
43703 end;
43704 {$ELSE ASM_VERSION} //Pascal
43705 function TControl.GetCurIndex: Integer;
43706 var I, J: Integer;
43707 begin
43708 Result := fCurIndex;
43709 if fCommandActions.aGetCurrent = 0 then
43710 Exit;
43711 I := 0;
43712 if fCommandActions.aGetCurrent = EM_LINEINDEX then
43713 Dec( I );
43714 J := 0;
43715 if fCommandActions.aGetCurrent = LVM_GETNEXTITEM then
43716 begin
43717 J := 2 {LVNI_SELECTED};
43718 Dec( I );
43719 end;
43720 Result := Perform( fCommandActions.aGetCurrent, I, J );
43721 end;
43722 {$ENDIF ASM_VERSION}
43724 {$IFDEF ASM_VERSION}
43725 //[procedure TControl.SetCurIndex]
43726 procedure TControl.SetCurIndex(const Value: Integer);
43728 MOVZX ECX, [EAX].fCommandActions.aSetCurrent
43729 JECXZ @@set_item_sel
43730 PUSHAD
43731 PUSH 0
43732 PUSH EDX
43733 PUSH ECX
43734 PUSH EAX
43735 CALL Perform
43736 POPAD
43737 CMP CX, TCM_SETCURSEL
43738 JNE @@exit
43739 PUSH TCN_SELCHANGE
43740 PUSH EAX // idfrom doesn't matter
43741 PUSH [EAX].fHandle
43742 PUSH ESP
43743 PUSH 0
43744 PUSH WM_NOTIFY
43745 PUSH EAX
43746 CALL Perform
43747 POP ECX
43748 POP ECX
43749 POP ECX
43750 @@exit:
43752 @@set_item_sel:
43753 INC ECX
43754 CALL SetItemSelected
43755 end;
43756 {$ELSE ASM_VERSION} //Pascal
43757 procedure TControl.SetCurIndex(const Value: Integer);
43758 var NMHdr: TNMHdr;
43759 begin
43760 if fCommandActions.aSetCurrent <> 0 then
43761 begin
43762 Perform( fCommandActions.aSetCurrent, Value, 0 );
43763 if fCommandActions.aSetCurrent = TCM_SETCURSEL then
43764 begin
43765 NMHdr.code := TCN_SELCHANGE;
43766 NMHdr.hwndFrom := fHandle;
43767 Perform( WM_NOTIFY, 0, Integer( @NMHdr ) );
43768 end;
43770 else
43771 ItemSelected[ Value ] := True;
43772 end;
43773 {$ENDIF ASM_VERSION}
43775 {$IFDEF ASM_VERSION}
43776 //[function TControl.GetTextAlign]
43777 function TControl.GetTextAlign: TTextAlign;
43779 PUSH EAX
43780 CALL UpdateWndStyles
43781 MOV ECX, [EAX].fStyle
43782 MOV EDX, dword ptr [EAX].fCommandActions.aTextAlignRight
43783 XOR EAX, EAX
43784 AND DX, CX
43785 JNZ @@ret_1
43786 SHR EDX, 16
43787 AND ECX, EDX
43788 JNZ @@ret_2
43789 POP EAX
43790 MOVZX EAX, [EAX].fTextAlign
43793 @@ret_2:INC EAX
43794 @@ret_1:INC EAX
43795 @@ret_0:POP ECX
43796 end;
43797 {$ELSE ASM_VERSION} //Pascal
43798 function TControl.GetTextAlign: TTextAlign;
43799 begin
43800 UpdateWndStyles;
43801 if (fStyle and fCommandActions.aTextAlignRight) = fCommandActions.aTextAlignRight then
43802 Result := taRight
43803 else
43804 if (fStyle and fCommandActions.aTextAlignCenter) = fCommandActions.aTextAlignCenter then
43805 Result := taCenter
43806 else
43807 Result := fTextAlign;
43808 end;
43809 {$ENDIF ASM_VERSION}
43811 {$IFDEF ASM_VERSION}
43812 //[function TControl.GetVerticalAlign]
43813 function TControl.GetVerticalAlign: TVerticalAlign;
43815 PUSH EAX
43816 CALL UpdateWndStyles
43817 MOV EDX, dword ptr [EAX].fCommandActions.aVertAlignCenter
43818 MOV ECX, [EAX].fStyle
43819 XOR EAX, EAX
43820 MOV DH, DL
43821 AND DL, CH
43822 JZ @@1
43823 CMP DL, DH
43824 JE @@ret_0
43825 @@1: SHR EDX, 16
43826 MOV DH, DL
43827 AND DL, CH
43828 JZ @@2
43829 CMP DL, DH
43830 JE @@ret_2
43831 @@2: POP EAX
43832 MOVZX EAX, [EAX].fVerticalAlign
43834 @@ret_2:INC EAX
43835 @@ret_1:INC EAX
43836 @@ret_0:POP ECX
43837 end;
43838 {$ELSE ASM_VERSION} //Pascal
43839 function TControl.GetVerticalAlign: TVerticalAlign;
43840 begin
43841 UpdateWndStyles;
43842 if (fStyle and (fCommandActions.aVertAlignCenter shl 8)) = (fCommandActions.aVertAlignCenter shl 8) then
43843 Result := vaCenter
43844 else
43845 if (fStyle and (fCommandActions.aVertAlignBottom shl 8)) = (fCommandActions.aVertAlignBottom shl 8) then
43846 Result := vaBottom
43847 else
43848 Result := fVerticalAlign;
43849 end;
43850 {$ENDIF ASM_VERSION}
43852 {$IFDEF ASM_VERSION}
43853 //[procedure TControl.SetTextAlign]
43854 procedure TControl.SetTextAlign(const Value: TTextAlign);
43856 MOV [EAX].fTextAlign, DL
43857 XOR ECX, ECX
43858 MOV CX, [EAX].fCommandActions.aTextAlignLeft
43859 OR CX, [EAX].fCommandActions.aTextAlignCenter
43860 OR CX, [EAX].fCommandActions.aTextAlignRight
43861 NOT ECX
43862 AND ECX, [EAX].fStyle
43864 AND EDX, 3
43865 OR CX, [EAX + EDX * 2].fCommandActions.aTextAlignLeft
43867 MOV DL, [EAX].fCommandActions.aTextAlignMask
43868 NOT EDX
43869 AND EDX, ECX
43870 CALL SetStyle
43871 end;
43872 {$ELSE ASM_VERSION} //Pascal
43873 procedure TControl.SetTextAlign(const Value: TTextAlign);
43874 var NewStyle: DWORD;
43875 begin
43876 fTextAlign := Value;
43877 NewStyle := 0;
43878 with fCommandActions do
43879 case Value of
43880 taLeft: NewStyle := fStyle and not DWORD(aTextAlignCenter or aTextAlignRight)
43881 or aTextAlignLeft;
43882 taRight: NewStyle := fStyle and not DWORD(aTextAlignLeft or aTextAlignCenter)
43883 or aTextAlignRight;
43884 taCenter: NewStyle := fStyle and not DWORD(aTextAlignLeft or aTextAlignRight)
43885 or aTextAlignCenter;
43886 end;
43887 NewStyle := NewStyle and not DWORD(fCommandActions.aTextAlignMask);
43888 Style := NewStyle;
43889 end;
43890 {$ENDIF ASM_VERSION}
43892 {$IFDEF ASM_noVERSION}
43893 //[procedure TControl.SetVerticalAlign]
43894 procedure TControl.SetVerticalAlign(const Value: TVerticalAlign);
43896 MOV [EAX].fVerticalAlign, DL
43897 XOR ECX, ECX
43898 MOV CX, word ptr [EAX].fCommandActions.aVertAlignTop
43899 OR CH, CL
43900 MOV CL, 0
43901 NOT ECX
43902 AND ECX, [EAX].fStyle
43903 AND EDX, 3
43904 MOV DH, [EAX + EDX].fCommandActions.aVertAlignCenter
43905 MOV DL, 0
43906 OR EDX, ECX
43907 CALL SetStyle
43908 end;
43909 {$ELSE ASM_VERSION} //Pascal
43910 procedure TControl.SetVerticalAlign(const Value: TVerticalAlign);
43911 var NewStyle: DWORD;
43912 begin
43913 fVerticalAlign := Value;
43914 with fCommandActions do
43915 begin
43916 NewStyle := fStyle and not DWORD((aVertAlignTop or aVertAlignCenter or aVertAlignBottom) shl 8);
43917 case Value of
43918 vaCenter: NewStyle := NewStyle or (aVertAlignCenter shl 8);
43919 vaTop: NewStyle := NewStyle or (aVertAlignTop shl 8);
43920 vaBottom: NewStyle := NewStyle or (aVertAlignBottom shl 8);
43921 end;
43922 end;
43923 Style := NewStyle;
43924 end;
43925 {$ENDIF ASM_VERSION}
43927 {$IFDEF ASM_noVERSION}
43928 //[function TControl.Dc2Canvas]
43929 function TControl.Dc2Canvas( Sender: PCanvas ): HDC;
43931 MOV ECX, [EAX].fPaintDC
43932 JECXZ @@chk_fHandle
43933 PUSH ECX
43934 XCHG EAX, EDX // EAX <= Sender
43935 MOV EDX, ECX // EDX <= fPaintDC
43936 PUSH EAX
43937 CALL TCanvas.SetHandle
43938 POP EAX
43939 MOV [EAX].TCanvas.fIsPaintDC, 1
43940 POP ECX
43941 @@ret_ECX:
43942 XCHG EAX, ECX
43944 @@chk_fHandle:
43945 MOV ECX, [EDX].TCanvas.fHandle
43946 INC ECX
43947 LOOP @@ret_ECX
43948 CALL GetWindowHandle
43949 PUSH EAX
43950 CALL GetDC
43951 end;
43952 {$ELSE ASM_VERSION} //Pascal
43953 function TControl.Dc2Canvas( Sender: PCanvas ): HDC;
43954 begin
43955 if fPaintDC <> 0 then
43956 begin
43957 Result := fPaintDC;
43958 Sender.SetHandle( Result );
43959 Sender.fIsPaintDC := True;
43961 else
43962 begin
43963 if Sender.fHandle <> 0 then
43964 Result := Sender.fHandle
43965 else
43966 Result := GetDC( GetWindowHandle );
43967 end;
43968 end;
43969 {$ENDIF ASM_VERSION}
43971 {$IFDEF ASM_VERSION}
43972 //[function TControl.GetCanvas]
43973 function TControl.GetCanvas: PCanvas;
43975 PUSH EBX
43976 PUSH ESI
43977 XCHG EBX, EAX
43979 MOV ESI, [EBX].fCanvas
43980 TEST ESI, ESI
43981 JNZ @@exit
43983 XOR EAX, EAX
43984 CALL NewCanvas
43985 MOV [EBX].fCanvas, EAX
43986 MOV [EAX].TCanvas.fOwnerControl, EBX
43987 MOV [EAX].TCanvas.fOnGetHandle.TMethod.Code, offset[ DC2Canvas ]
43988 MOV [EAX].TCanvas.fOnGetHandle.TMethod.Data, EBX
43989 XCHG ESI, EAX
43991 MOV ECX, [EBX].fFont
43992 JECXZ @@exit
43994 MOV EAX, [ESI].TCanvas.fFont
43995 MOV EDX, ECX
43996 CALL TGraphicTool.Assign
43997 MOV [ESI].TCanvas.fFont, EAX
43999 MOV ECX, [EBX].fBrush
44000 JECXZ @@exit
44002 MOV EAX, [ESI].TCanvas.fBrush
44003 MOV EDX, ECX
44004 CALL TGraphicTool.Assign
44005 MOV [ESI].TCanvas.fBrush, EAX
44007 @@exit: XCHG EAX, ESI
44008 POP ESI
44009 POP EBX
44010 end;
44011 {$ELSE ASM_VERSION} //Pascal
44012 function TControl.GetCanvas: PCanvas;
44013 begin
44014 if not assigned( fCanvas ) then
44015 begin
44016 fCanvas := NewCanvas( 0 );
44017 fCanvas.OnGetHandle := Dc2Canvas;
44018 fCanvas.fOwnerControl := @Self;
44019 if assigned( fFont ) then
44020 fCanvas.fFont := fCanvas.fFont.Assign( fFont );
44021 if assigned( fBrush ) then
44022 fCanvas.fBrush := fCanvas.fBrush.Assign( fBrush );
44023 end;
44024 Result := fCanvas;
44025 end;
44026 {$ENDIF ASM_VERSION}
44028 //[function TControl.DblBufTopParent]
44029 function TControl.DblBufTopParent: PControl;
44030 var Ctl: PControl;
44031 begin
44032 Result := nil;
44033 Ctl := @ Self;
44034 while Ctl <> nil do
44035 begin
44036 if Ctl.fDoubleBuffered then
44037 Result := Ctl;
44038 Ctl := Ctl.fParent;
44039 end;
44040 end;
44042 //[procedure InvalidateDblBufParent]
44043 procedure InvalidateDblBufParent( Sender: PControl );
44044 var C: PControl;
44045 begin
44046 C := Sender.DblBufTopParent;
44047 if C <> nil then
44048 InvalidateRect( C.fHandle, nil, TRUE );
44049 end;
44051 //[function WndFuncPreventDraw]
44052 function WndFuncPreventDraw( W: HWnd; Msg: Cardinal; wParam, lParam: Integer ): Integer; stdcall;
44053 var C: PControl;
44054 PrntW: HWnd;
44055 //********************************************************** Added By M.Gerasimov
44057 PrevProc:Pointer;
44059 //********************************************************** Added By M.Gerasimov
44060 begin
44061 //if not AppletTerminated then
44062 case Msg of
44063 WM_NCPAINT,
44064 //WM_PAINT,
44065 WM_ERASEBKGND:
44066 begin
44067 C := Pointer( GetProp( W, ID_SELF ) );
44068 if C = nil then
44069 begin
44070 PrntW := GetParent( W );
44071 if PrntW <> 0 then
44072 begin
44073 C := Pointer( GetProp( PrntW, ID_SELF ) );
44074 if (C <> nil) and not C.fCannotDoubleBuf and
44075 (C.DblBufTopParent <> nil) and
44076 (not C.DblBufTopParent.fDblBufPainting) then
44077 begin
44078 case Msg of
44079 WM_NCPAINT: Result := 0;
44080 WM_PAINT: Result := 0;
44081 else Result := 1;
44082 end;
44083 Exit;
44084 end;
44085 end;
44086 end;
44087 end;
44088 end;
44089 //********************************************************** By M.Gerasimov
44091 PrevProc:=Pointer(GetProp( W, ID_PREVPROC ));
44092 if PrevProc <> Nil then
44093 Result := CallWindowProc( PrevProc , W, Msg, wParam, lParam )
44094 else
44095 Result:=0;
44097 //********************************************************** Remarked By M.Gerasimov
44098 //Result := CallWindowProc( Pointer( GetProp( W, 'PREV_PROC' ) ),
44099 // W, Msg, wParam, lParam );
44100 //******************************************************************************
44101 end;
44103 //[procedure DblBufCreateWndProc]
44104 procedure DblBufCreateWndProc( Sender: PControl );
44105 var Chld: HWnd;
44106 PrevProc: DWORD;
44107 begin
44108 Chld := GetWindow( Sender.fHandle, GW_CHILD );
44109 while Chld <> 0 do
44110 begin
44111 //********************************************************** Changed By M.Gerasimov
44112 // if GetProp( Chld, 'PREV_PROC' ) = 0 then
44113 //**********************************************************
44114 if GetProp( Chld, ID_PREVPROC ) = 0 then //
44115 //**********************************************************
44116 begin
44117 PrevProc :=
44118 SetWindowLong( Chld, GWL_WNDPROC, Longint( @WndFuncPreventDraw ) );
44119 //********************************************************** Changed By M.Gerasimov
44120 // SetProp( Chld, 'PREV_PROC', PrevProc );
44121 //**********************************************************
44122 SetProp( Chld, ID_PREVPROC, PrevProc ); //
44123 //**********************************************************
44124 end;
44125 Chld := GetWindow( Chld, GW_HWNDNEXT );
44126 end;
44127 end;
44129 //[procedure TControl.SetDoubleBuffered]
44130 procedure TControl.SetDoubleBuffered(const Value: Boolean);
44131 begin
44132 if CannotDoubleBuf then Exit;
44133 fDoubleBuffered := Value;
44134 Global_OnBufferedDraw := WndProcBufferedDraw;
44135 Global_Invalidate := @ InvalidateDblBufParent;
44136 Global_DblBufCreateWnd := @ DblBufCreateWndProc;
44137 end;
44139 {$IFDEF ASM_VERSION}
44140 //[procedure TControl.SetTransparent]
44141 procedure TControl.SetTransparent(const Value: Boolean);
44143 CMP [EAX].fTransparent, DL
44144 JZ @@exit
44145 MOV [EAX].fTransparent, DL
44146 TEST DL, DL
44147 JZ @@exit
44148 MOV ECX, [EAX].fParent
44149 JECXZ @@exit
44150 XCHG EAX, ECX
44151 CALL SetDoubleBuffered
44152 @@exit:
44153 end;
44154 {$ELSE ASM_VERSION} //Pascal
44155 procedure TControl.SetTransparent(const Value: Boolean);
44156 begin
44157 if fTransparent = Value then Exit;
44158 fTransparent := Value;
44159 //ExStyle := ExStyle or WS_EX_TRANSPARENT;
44160 if fParent = nil then Exit;
44161 if Value then
44162 fParent.DoubleBuffered := True;
44163 end;
44164 {$ENDIF ASM_VERSION}
44166 //[function TControl.SetBorder]
44167 function TControl.SetBorder( Value: Integer ): PControl;
44168 begin
44169 fMargin := Value;
44170 Result := @ Self;
44171 end;
44173 { TTrayIcon }
44175 var FTrayItems: PList;
44177 //[FUNCTION WndProcTray]
44178 {$IFDEF ASM_noVERSION}
44179 function WndProcTray( Control: PControl; var Msg: TMsg; var Rslt: Integer ) : Boolean;
44181 PUSH ECX
44182 MOV ECX, [EDX].TMsg.message
44183 CMP CX, CM_TRAYICON
44184 JNE @@1
44186 MOV ECX, [EDX].TMsg.lParam
44187 MOV EDX, [EDX].TMsg.wParam
44188 MOV EAX, [EDX].TTrayIcon.fOnMouse.TMethod.Data
44189 CMP word ptr [EDX].TTrayIcon.fOnMouse.TMethod.Code+2, 0
44190 JE @@no_on
44192 CALL [EDX].TTrayIcon.fOnMouse.TMethod.Code
44193 @@no_on:
44194 POP ECX
44195 XOR EAX, EAX
44196 MOV [ECX], EAX
44197 INC EAX
44200 @@1:
44201 SUB ECX, WM_CLOSE
44202 JNE @@exit_0
44203 @@2:
44205 POP ECX
44206 PUSH EBX
44207 XCHG EBX, EAX
44209 MOV EAX, [EBX].TControl.fHandle
44210 CMP EAX, [EDX].TMsg.hwnd
44211 JNE @@otherwin
44213 MOV EDX, [FTrayItems]
44214 MOV ECX, [EDX].TList.fCount
44215 MOV EDX, [EDX].TList.fItems
44216 @@loop:
44217 MOV EAX, [EDX + ECX*4 - 4]
44218 CMP [EAX].TTray.FNoAutoDeactivate, 0
44219 JNZ @@3
44220 CMP [EAX].TTrayIcon.fControl, EBX
44221 JNE @@3
44222 PUSHAD
44223 XOR EDX, EDX
44224 CALL TTrayIcon.SetActive
44225 POPAD
44226 @@3: LOOP @@loop
44228 @@otherwin:
44229 POP EBX
44230 PUSH ECX
44232 @@exit_0:
44233 XOR EAX, EAX
44234 POP ECX
44235 end;
44236 {$ELSE ASM_VERSION} //Pascal
44237 function WndProcTray( Control: PControl; var Msg: TMsg; var Rslt: Integer ) : Boolean;
44238 var Self_: PTrayIcon;
44239 I : Integer;
44240 begin
44241 Result := False;
44242 case Msg.message of
44243 CM_TRAYICON:
44244 begin
44245 Self_ := Pointer( Msg.wParam );
44246 if Assigned( Self_.FOnMouse ) then
44247 Self_.FOnMouse( @Self_, Msg.lParam );
44248 Rslt := 0;
44249 Result := True;
44250 end;
44251 WM_CLOSE:
44252 if Msg.hwnd = Control.fHandle then
44253 begin
44254 if FTrayItems <> nil then // ?????????????????
44255 for I := FTrayItems.Count - 1 downto 0 do
44256 begin
44257 Self_ := FTrayItems.Items[ I ];
44258 if not Self_.FNoAutoDeactivate then
44259 if Self_.FControl = Control then
44260 Self_.Active := False;
44261 end;
44262 end;
44263 end;
44264 end;
44265 {$ENDIF ASM_VERSION}
44266 //[END WndProcTray]
44268 //[FUNCTION _NewTrayIcon]
44269 {$IFDEF ASM_VERSION}
44270 function _NewTrayIcon: PTrayIcon;
44271 begin
44272 New(Result,Create);
44273 end;
44274 {$ENDIF ASM_VERSION}
44275 //[END _NewTrayIcon]
44277 function WndProcTrayIconWnd( Wnd: HWnd; Msg: DWORD; wParam, lParam: Integer ): Integer;
44278 stdcall;
44279 var PrevProc: function ( Wnd: HWnd; Msg: DWORD;
44280 wParam, lParam: Integer ): Integer; stdcall;
44281 var Tr: PTrayIcon;
44282 begin
44283 PrevProc := Pointer( GetProp( Wnd, 'TRAYSAVEPROC' ) );
44284 if Msg = CM_TRAYICON then
44285 begin
44286 Tr := Pointer( wParam );
44287 if Assigned( Tr.FOnMouse ) then
44288 Tr.FOnMouse( Tr, lParam );
44289 Result := 0;
44290 Exit;
44292 else
44293 if Msg = WM_CLOSE then
44294 begin
44295 if Assigned( PrevProc ) then
44296 begin
44297 SetWindowLong( Wnd, GWL_WNDPROC, Integer( @ PrevProc ) );
44298 RemoveProp( Wnd, 'TRAYSAVEPROC' );
44299 PostMessage( Wnd, WM_CLOSE, wParam, lParam );
44300 Result := 0;
44301 Exit;
44302 //Wnd := 0;
44303 end;
44304 end;
44305 if (Wnd <> 0) and IsWindow( Wnd ) and Assigned( PrevProc ) then
44306 Result := PrevProc( Wnd, Msg, wParam, lParam )
44307 else
44308 Result := DefWindowProc( Wnd, Msg, wParam, lParam );
44309 end;
44311 //[PROCEDURE TTrayIcon.AttachProc2Wnd]
44312 procedure TTrayIcon.AttachProc2Wnd;
44313 begin
44314 if FWnd = 0 then Exit;
44315 if GetProp( FWnd, 'TRAYSAVEPROC' ) <> 0 then Exit; // already attached
44316 SetProp( FWnd, 'TRAYSAVEPROC', GetWindowLong( FWnd, GWL_WNDPROC ) );
44317 SetWindowLong( FWnd, GWL_WNDPROC, Integer( @ WndProcTrayIconWnd ) );
44318 end;
44319 // [END TTrayIcon.AttachProc2Wnd]
44321 // [PROCEDURE TTrayIcon.DetachProc2Wnd]
44322 procedure TTrayIcon.DetachProc2Wnd;
44323 var OldProc: function ( Wnd: HWnd; Msg: DWORD;
44324 wParam, lParam: Integer ): Integer; stdcall;
44325 begin
44326 if FWnd = 0 then Exit;
44327 OldProc := Pointer( GetProp( FWnd, 'TRAYSAVEPROC' ) );
44328 if not Assigned( OldProc ) then Exit; // not attached
44329 SetWindowLong( FWnd, GWL_WNDPROC, Integer( @ OldProc ) );
44330 RemoveProp( FWnd, 'TRAYSAVEPROC' );
44331 end;
44332 // [END TTrayIcon.DetachProc2Wnd]
44334 //[FUNCTION NewTrayIcon]
44335 {$IFDEF ASM_VERSION}
44336 function NewTrayIcon( Wnd: PControl; Icon: HIcon ): PTrayIcon;
44338 PUSH EBX
44339 PUSH EDX // push Icon
44340 PUSH EAX // push Wnd
44341 CALL _NewTrayIcon
44342 XCHG EBX, EAX
44344 MOV EAX, [FTrayItems]
44345 TEST EAX, EAX
44346 JNZ @@1
44347 CALL NewList
44348 MOV [FTrayItems], EAX
44349 @@1:
44350 MOV EDX, EBX
44351 CALL TList.Add
44353 POP EAX //Wnd
44354 MOV [EBX].TTrayIcon.fControl, EAX
44355 POP [EBX].TTrayIcon.fIcon //Icon
44357 MOV EDX, offset[WndProcTray]
44358 TEST EAX, EAX
44359 JZ @@2
44360 CALL TControl.AttachProc
44361 @@2:
44362 MOV DL, 1
44363 MOV EAX, EBX
44364 CALL TTrayIcon.SetActive
44365 XCHG EAX, EBX
44366 POP EBX
44367 end;
44368 {$ELSE ASM_VERSION} //Pascal
44369 function NewTrayIcon( Wnd: PControl; Icon: HIcon ): PTrayIcon;
44370 begin
44371 if FTrayItems = nil then
44372 FTrayItems := NewList;
44374 New( Result, Create );
44375 {+}{++}(*Result := PTrayIcon.Create;*){--}
44376 FTrayItems.Add( Result );
44377 if Wnd <> nil then
44378 Wnd.AttachProc( WndProcTray );
44379 Result.FControl := Wnd;
44380 Result.FIcon := Icon;
44381 Result.Active := True;
44382 end;
44383 {$ENDIF ASM_VERSION}
44384 //[END NewTrayIcon]
44386 var fRecreateMsg: DWORD;
44388 //[FUNCTION WndProcRecreateTrayIcons]
44389 {$IFDEF ASM_VERSION}
44390 function WndProcRecreateTrayIcons( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
44391 asm //cmd //opd
44392 MOV ECX, [fRecreateMsg]
44393 CMP word ptr [EDX].TMsg.message, CX
44394 JNE @@ret_false
44395 PUSH ESI
44396 MOV ESI, [FTrayItems]
44397 MOV ECX, [ESI].TList.fCount
44398 MOV ESI, [ESI].TList.fItems
44399 //JECXZ @@e_loo
44400 @@loo: PUSH ECX
44401 LODSD
44402 MOV DL, [EAX].TTrayIcon.fAutoRecreate
44403 AND DL, [EAX].TTrayIcon.fActive
44404 JZ @@nx
44405 DEC [EAX].TTrayIcon.fActive
44406 CALL TTrayIcon.SetActive
44407 @@nx: POP ECX
44408 LOOP @@loo
44409 @@e_loo:POP ESI
44410 @@ret_false:
44411 XOR EAX, EAX
44412 end;
44413 {$ELSE ASM_VERSION} //Pascal
44414 function WndProcRecreateTrayIcons( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
44415 var I: Integer;
44416 TI: PTrayIcon;
44417 begin
44418 if Msg.message = fRecreateMsg then
44419 begin
44420 for I := 0 to FTrayItems.fCount - 1 do
44421 begin
44422 TI := FTrayItems.Items[ I ];
44423 if TI.fAutoRecreate then
44424 if TI.fActive then
44425 begin
44426 TI.fActive := False;
44427 TI.Active := True;
44428 end;
44429 end;
44430 end;
44431 Result := False;
44432 end;
44433 {$ENDIF ASM_VERSION}
44434 //[END WndProcRecreateTrayIcons]
44436 const
44437 TaskbarCreatedMsg: array[ 0..14 ] of Char = ('T','a','s','k','b','a','r',
44438 'C','r','e','a','t','e','d',#0);
44439 {$IFDEF ASM_VERSION}
44440 //[procedure TTrayIcon.SetAutoRecreate]
44441 procedure TTrayIcon.SetAutoRecreate(const Value: Boolean);
44442 asm //cmd //opd
44443 MOV [EAX].fAutoRecreate, DL
44444 MOV EAX, [EAX].FControl
44445 CALL TControl.ParentForm
44446 MOV EDX, offset[WndProcRecreateTrayIcons]
44447 CALL TControl.AttachProc
44448 PUSH offset[TaskbarCreatedMsg]
44449 CALL RegisterWindowMessage
44450 MOV [fRecreateMsg], EAX
44451 end;
44452 {$ELSE ASM_VERSION} //Pascal
44453 procedure TTrayIcon.SetAutoRecreate(const Value: Boolean);
44454 begin
44455 fAutoRecreate := Value;
44456 FControl.ParentForm.AttachProc( WndProcRecreateTrayIcons );
44457 fRecreateMsg := RegisterWindowMessage( TaskbarCreatedMsg );
44458 end;
44459 {$ENDIF ASM_VERSION}
44461 {$IFDEF ASM_VERSION}
44462 //[destructor TTrayIcon.Destroy]
44463 destructor TTrayIcon.Destroy;
44465 PUSH EBX
44466 PUSH ESI
44467 MOV EBX, EAX
44468 XOR EDX, EDX
44469 CALL SetActive
44471 MOV ECX, [EBX].fIcon
44472 JECXZ @@icon_destroyed
44473 PUSH ECX
44474 CALL DestroyIcon
44475 @@icon_destroyed:
44477 MOV EDX, EBX
44478 MOV ESI, [FTrayItems]
44479 MOV EAX, ESI
44480 CALL TList.IndexOf
44481 TEST EAX, EAX
44482 JL @@fin
44483 XCHG EDX, EAX
44484 MOV EAX, ESI
44485 CALL TList.Delete
44486 MOV EAX, [ESI].TList.fCount
44487 TEST EAX, EAX
44488 JNZ @@fin
44489 XCHG EAX, [FTrayItems]
44490 CALL TObj.Free
44491 @@fin: LEA EAX, [EBX].FTooltip
44492 CALL System.@LStrClr
44493 XCHG EAX, EBX
44494 CALL TObj.Destroy
44495 POP ESI
44496 POP EBX
44497 end;
44498 {$ELSE ASM_VERSION} //Pascal
44499 destructor TTrayIcon.Destroy;
44500 begin
44501 Active := False;
44503 if fIcon <> 0 then
44504 DestroyIcon( fIcon );
44506 FTrayItems.Remove( @ Self );
44507 if FTrayItems.Count = 0 then
44508 Free_And_Nil( FTrayItems );
44509 FTooltip := '';
44510 inherited;
44511 end;
44512 {$ENDIF ASM_VERSION}
44514 {$IFDEF ASM_VERSION}
44515 //[procedure TTrayIcon.SetActive]
44516 procedure TTrayIcon.SetActive(const Value: Boolean);
44518 CMP [EAX].fActive, DL
44519 JE @@exit
44520 MOV ECX, [EAX].fIcon
44521 JECXZ @@exit
44522 PUSH EDX
44523 PUSH EAX
44524 MOV ECX, [EAX].FWnd
44525 INC ECX
44526 LOOP @@1
44527 MOV ECX, [EAX].fControl
44528 XOR EAX, EAX
44529 JECXZ @@1
44530 XCHG EAX, ECX
44531 CALL TControl.GetWindowHandle
44532 @@1:
44533 POP ECX
44534 POP EDX
44535 XCHG EAX, ECX
44536 JECXZ @@exit
44537 MOV [EAX].fActive, DL
44538 MOVZX EDX, DL
44539 XOR DL, 1
44540 ADD EDX, EDX
44541 CALL SetTrayIcon
44542 @@exit:
44543 end;
44544 {$ELSE ASM_VERSION} //Pascal
44545 procedure TTrayIcon.SetActive(const Value: Boolean);
44546 begin
44547 if FActive = Value then Exit;
44548 if FIcon = 0 then Exit;
44549 if (Wnd = 0) and ((FControl = nil) or (FControl.GetWindowHandle = 0)) then Exit;
44550 FActive := Value;
44551 if Value then
44552 SetTrayIcon( NIM_ADD )
44553 else
44554 SetTrayIcon( NIM_DELETE );
44555 end;
44556 {$ENDIF ASM_VERSION}
44558 {$IFDEF ASM_VERSION}
44559 //[procedure TTrayIcon.SetIcon]
44560 procedure TTrayIcon.SetIcon(const Value: HIcon);
44562 MOV ECX, [EAX].fIcon
44563 CMP ECX, EDX
44564 JE @@exit
44565 MOV [EAX].fIcon, EDX
44566 XOR EDX, EDX
44567 JECXZ @@nim_add
44568 INC EDX // NIM_MODIFY = 1
44569 @@nim_add:
44570 MOVZX ECX, [EAX].fActive
44571 JECXZ @@exit
44572 CALL SetTrayIcon
44573 @@exit:
44574 end;
44575 {$ELSE ASM_VERSION} //Pascal
44576 procedure TTrayIcon.SetIcon(const Value: HIcon);
44577 var Cmd : DWORD;
44578 begin
44579 if FIcon = Value then Exit;
44580 // Previous icon is not destroying. This is normal for
44581 // icons, loaded from resources using LoadIcon. For icons,
44582 // created using CreateIconIndirect, You have to call
44583 // DestroyIcon manually.
44584 Cmd := NIM_MODIFY;
44585 if FIcon = 0 then
44586 Cmd := NIM_ADD;
44587 FIcon := Value;
44588 if FActive then
44589 SetTrayIcon( Cmd );
44590 end;
44591 {$ENDIF ASM_VERSION}
44593 {$IFDEF ASM_VERSION}
44594 //[procedure TTrayIcon.SetTooltip]
44595 procedure TTrayIcon.SetTooltip(const Value: String);
44597 PUSH EBX
44598 XCHG EBX, EAX
44599 MOV EAX, [EBX].fTooltip
44600 PUSH EDX
44601 CALL System.@LStrCmp
44602 POP EDX
44603 JE @@exit
44604 LEA EAX, [EBX].fTooltip
44605 CALL System.@LStrAsg
44606 CMP [EBX].fActive, 0
44607 JE @@exit
44608 XOR EDX, EDX
44609 INC EDX // EDX = NIM_MODIFY
44610 XCHG EAX, EBX
44611 CALL SetTrayIcon
44612 @@exit:
44613 POP EBX
44614 end;
44615 {$ELSE ASM_VERSION} //Pascal
44616 procedure TTrayIcon.SetTooltip(const Value: String);
44617 begin
44618 if FTooltip = Value then Exit;
44619 FTooltip := Value;
44620 if Active then
44621 SetTrayIcon( NIM_MODIFY );
44622 end;
44623 {$ENDIF ASM_VERSION}
44625 {$IFDEF ASM_VERSION}
44626 //[procedure TTrayIcon.SetTrayIcon]
44627 procedure TTrayIcon.SetTrayIcon(const Value: DWORD);
44628 const sz_tid = sizeof( TNotifyIconData );
44630 //MOV ECX, [EAX].fIcon
44631 //JECXZ @@exit
44633 CMP [AppletTerminated], 0
44634 JE @@1
44635 MOV DL, NIM_DELETE
44636 @@1:
44637 PUSH EBX
44638 PUSH ESI
44639 MOV ESI, EAX
44640 MOV EBX, EDX
44642 XOR ECX, ECX
44643 PUSH ECX
44644 ADD ESP, -60
44645 MOV EDX, [ESI].fToolTip
44646 CALL EDX2PChar
44647 MOV EAX, ESP
44648 MOV CL, 63
44649 CALL StrLCopy
44651 PUSH [ESI].fIcon
44652 PUSH CM_TRAYICON
44653 XOR EDX, EDX
44654 CMP BL, NIM_DELETE
44655 JE @@2
44656 MOV DL, NIF_ICON or NIF_MESSAGE or NIF_TIP
44657 @@2: PUSH EDX
44658 PUSH ESI
44659 MOV EAX, [ESI].FWnd
44660 TEST EAX, EAX
44661 JNZ @@3
44662 MOV EAX, [ESI].fControl
44663 MOV EAX, [EAX].TControl.fHandle
44664 @@3:
44665 PUSH EAX
44666 PUSH sz_tid
44668 PUSH ESP
44669 PUSH EBX
44670 CALL Shell_NotifyIcon
44672 ADD ESP, sz_tid
44673 POP ESI
44674 POP EBX
44675 @@exit:
44676 end;
44677 {$ELSE ASM_VERSION} //Pascal
44678 procedure TTrayIcon.SetTrayIcon(const Value: DWORD);
44679 var NID : TNotifyIconData;
44680 L : Integer;
44681 V : DWORD;
44682 begin
44683 //if FIcon = 0 then Exit; - already tested
44684 V := Value;
44685 if AppletTerminated then
44686 V := NIM_DELETE;
44687 if Wnd <> 0 then
44688 NID.Wnd := Wnd
44689 else
44690 NID.Wnd := FControl.fHandle;
44692 NID.cbSize := Sizeof( NID );
44693 NID.uID := DWORD( @Self );
44694 NID.uFlags := NIF_ICON or NIF_MESSAGE or NIF_TIP;
44695 if V = NIM_DELETE then
44696 NID.uFlags := 0;
44697 NID.uCallbackMessage := CM_TRAYICON;
44698 NID.hIcon := FIcon;
44699 L := Length( FToolTip );
44700 if L > 63 then L := 63;
44701 Move( FTooltip[1], NID.szTip[0], Min( 63, L ) );
44702 NID.szTip[ L ] := #0;
44704 Shell_NotifyIcon( V, @NID );
44705 end;
44706 {$ENDIF ASM_VERSION}
44708 { -- JustOne -- }
44710 var JustOneMutex: THandle;
44712 //[FUNCTION WndProcJustOne]
44713 {$IFDEF ASM_VERSION}
44714 function WndProcJustOne( Control: PControl; var Msg: TMsg; var Rslt: Integer ) : Boolean;
44716 MOV ECX, [EDX].TMsg.message
44717 SUB ECX, WM_CLOSE
44718 JE @@1
44719 SUB ECX, WM_NCDESTROY - WM_CLOSE
44720 JNE @@exit
44721 @@1:
44722 XCHG ECX, [JustOneMutex]
44723 JECXZ @@exit
44724 PUSH ECX
44725 PUSH ECX
44726 CALL ReleaseMutex
44727 CALL CloseHandle
44729 @@exit:
44730 XOR EAX, EAX
44731 end;
44732 {$ELSE ASM_VERSION} //Pascal
44733 function WndProcJustOne( Control: PControl; var Msg: TMsg; var Rslt: Integer ) : Boolean;
44734 begin
44735 Result := False;
44736 case Msg.message of
44737 WM_CLOSE, WM_NCDESTROY:
44738 if LongBool( JustOneMutex ) then
44739 begin
44740 ReleaseMutex( JustOneMutex );
44741 CloseHandle( JustOneMutex );
44742 JustOneMutex := 0;
44743 end;
44744 end;
44745 end;
44746 {$ENDIF ASM_VERSION}
44747 //[END WndProcJustOne]
44749 //[FUNCTION JustOne]
44750 {$IFDEF ASM_VERSION}
44751 function JustOne( Wnd: PControl; const Identifier : String ) : Boolean;
44752 const JOcs: PChar = 'KOL.Just1.CrtSec';
44754 PUSH EBX
44755 PUSH ESI
44756 XOR ESI, ESI
44757 PUSH EDI
44758 XCHG EBX, EAX
44760 CALL EDX2PChar
44761 PUSH EDX
44763 PUSH [JOcs]
44764 PUSH 1
44765 PUSH ESI
44766 MOV EDI, offset[CreateMutex]
44767 CALL EDI
44769 POP EDX
44770 TEST EAX, EAX
44771 JZ @@exit //
44772 PUSH EAX
44773 PUSH EAX
44775 PUSH EDX
44776 PUSH ESI
44777 PUSH ESI
44778 CALL EDI
44779 MOV [JustOneMutex], EAX
44780 TEST EAX, EAX
44781 JE @@1 //
44783 PUSH ESI
44784 PUSH EAX
44785 CALL WaitForSingleObject
44786 SUB EAX, WAIT_TIMEOUT
44787 JE @@1
44789 INC ESI
44790 @@1:
44791 //MOV [EBX].TControl.fWndProcJustOne, offset[WndProcJustOne]
44792 XCHG EAX, EBX
44793 MOV EDX, offset[WndProcJustOne]
44794 CALL TControl.AttachProc
44796 CALL ReleaseMutex
44797 CALL CloseHandle
44799 @@exit:
44800 XCHG EAX, ESI
44801 POP EDI
44802 POP ESI
44803 POP EBX
44804 end;
44805 {$ELSE ASM_VERSION} //Pascal
44806 function JustOne( Wnd: PControl; const Identifier : String ) : Boolean;
44807 var CritSecMutex : THandle;
44808 DW : Longint;
44809 begin
44810 Result := False;
44811 CritSecMutex := CreateMutex( nil, True, PChar( 'KOL.Just1.CrtSec' ) );
44812 if CritSecMutex = 0 then Exit;
44814 JustOneMutex := CreateMutex( nil, False, PChar( Identifier ) );
44815 if JustOneMutex <> 0 then
44816 begin
44817 DW := WaitForSingleObject( JustOneMutex, 0 );
44818 Result := (DW <> WAIT_TIMEOUT);
44819 end;
44821 //Wnd.fWndProcJustOne := WndProcJustOne;
44822 Wnd.AttachProc( WndProcJustOne );
44824 ReleaseMutex( CritSecMutex );
44825 CloseHandle( CritSecMutex );
44826 end;
44827 {$ENDIF ASM_VERSION}
44828 //[END JustOne]
44830 { JustOneNotify }
44833 OnAnotherInstance: TOnAnotherInstance;
44834 JustOneMsg: DWORD;
44836 //[FUNCTION WndProcJustOneNotify]
44837 {$IFDEF ASM_VERSION}
44838 function WndProcJustOneNotify( Control: PControl; var Msg: TMsg; var Rslt: Integer ) : Boolean;
44840 PUSH EBP
44841 MOV EBP, ESP
44842 PUSHAD
44843 CALL WndProcJustOne
44844 POPAD
44845 XOR EAX, EAX
44846 PUSH ECX
44847 MOV ECX, [EDX].TMsg.message
44848 SUB ECX, [JustOneMsg]
44849 POP ECX
44850 JNE @@exit
44851 MOV [ECX], EAX
44852 CMP [OnAnotherInstance].TMethod.Code, EAX
44853 JE @@exit_1
44855 //MOV EAX, (MAX_PATH + 3) and 0FFFFCh
44856 MOV AH, 2
44857 SUB ESP, EAX
44859 MOV ECX, ESP
44860 PUSH EAX
44861 PUSH ECX
44862 PUSH [EDX].TMsg.lParam
44863 CALL GetWindowText
44865 MOV EDX, ESP
44866 PUSH 0
44867 MOV EAX, ESP
44868 CALL System.@LStrFromPChar
44870 MOV EDX, [ESP]
44871 MOV EAX, [OnAnotherInstance].TMethod.Data
44872 CALL [OnAnotherInstance].TMethod.Code
44874 MOV EAX, ESP
44875 CALL System.@LStrClr
44876 @@exit_1:
44877 MOV AL, 1
44878 @@exit:
44879 MOV ESP, EBP
44880 POP EBP
44881 end;
44882 {$ELSE ASM_VERSION} //Pascal
44883 function WndProcJustOneNotify( Control: PControl; var Msg: TMsg; var Rslt: Integer ) : Boolean;
44884 var Buf : array[0..MAX_PATH] of Char;
44885 begin
44886 WndProcJustOne( Control, Msg, Rslt );
44887 Result := False;
44888 if Msg.message = JustOneMsg then
44889 begin
44890 Result := True;
44891 if assigned( OnAnotherInstance ) then
44892 begin
44893 GetWindowText( Msg.lParam, Buf, MAX_PATH );
44894 OnAnotherInstance( Buf );
44895 end;
44896 Rslt := 0;
44897 end;
44898 end;
44899 {$ENDIF ASM_VERSION}
44900 //[END WndProcJustOneNotify]
44902 // Redefine here incorrectly declared BroadcastSystemMessage API function.
44903 // It should not refer to BroadcastSystemMessageA, which is not present in
44904 // earlier versions of Windows95, but to BroadcastSystemMessage, which is
44905 // present in all Windows95/98/Me and NT/2K/XP.
44906 //[API BroadcastSystemMessage]
44907 function BroadcastSystemMessage(Flags: DWORD; Recipients: PDWORD;
44908 uiMessage: UINT; wParam: WPARAM; lParam: LPARAM): Longint; stdcall;
44909 external user32 name 'BroadcastSystemMessage';
44911 //[FUNCTION JustOneNotify]
44912 {$IFDEF ASM_VERSION}
44913 function JustOneNotify( Wnd: PControl; const Identifier : String;
44914 const aOnAnotherInstance: TOnAnotherInstance ) : Boolean;
44916 PUSHAD
44917 MOV EBP, ESP
44919 XCHG EAX, EDX
44920 PUSH EAX
44921 CALL System.@LStrLen
44922 POP EDX
44923 ADD EAX, EAX
44924 SUB ESP, EAX
44925 MOV EAX, ESP
44926 CALL StrPCopy
44927 PUSH '.ega'
44928 PUSH 'sseM'
44929 PUSH ESP
44930 CALL RegisterWindowMessage
44931 MOV [JustOneMsg], EAX
44932 TEST EAX, EAX
44934 MOV ESP, EBP
44935 POPAD
44936 JE @@exit_f
44938 PUSHAD
44939 CALL JustOne
44940 DEC AL
44941 POPAD
44942 JZ @@exit_t
44944 PUSH EBX
44945 XCHG EBX, EAX
44946 XOR EDX, EDX
44947 XCHG [EBX].TControl.fCaption, EDX
44948 PUSH EDX
44950 CALL GetCommandLine
44951 XCHG EDX, EAX
44952 MOV EAX, EBX
44953 CALL TControl.SetCaption
44954 MOV EAX, EBX
44955 CALL TControl.GetWindowHandle
44956 TEST EAX, EAX
44957 JZ @@rest_cap
44959 PUSH BSM_APPLICATIONS
44960 MOV EDX, ESP
44962 PUSH EAX
44963 PUSH 0
44964 PUSH [JustOneMsg]
44965 PUSH EDX
44966 PUSH BSF_QUERY or BSF_IGNORECURRENTTASK
44967 CALL BroadcastSystemMessage
44969 POP EDX
44970 @@rest_cap:
44971 XOR EDX, EDX
44972 MOV EAX, EBX
44973 CALL TControl.SetCaption
44974 POP EDX
44975 MOV [EBX].TControl.fCaption, EDX
44976 PUSH EDX
44977 PUSH [EBX].TControl.fHandle
44978 CALL SetWindowText
44979 POP EBX
44980 @@exit_f:
44981 XOR EAX, EAX
44982 POP EBP // because compiler inserts PUSH EBP;MOV EBP,ESP at the BEGIN
44985 @@exit_t:
44986 PUSHAD
44987 LEA ESI, [aOnAnotherInstance]
44988 LEA EDI, [OnAnotherInstance]
44989 MOVSD
44990 MOVSD
44991 //MOV [EAX].TControl.fWndProcJustOne, offset[WndProcJustOneNotify]
44992 MOV EDX, offset[WndProcJustOneNotify]
44993 CALL TControl.AttachProc
44995 POPAD
44996 MOV AL, 1
44997 end;
44998 {$ELSE ASM_VERSION} //Pascal
44999 function JustOneNotify( Wnd: PControl; const Identifier : String;
45000 const aOnAnotherInstance: TOnAnotherInstance ) : Boolean;
45001 var Recipients : DWord;
45002 OldCap: String;
45003 begin
45004 Result := False;
45005 JustOneMsg := RegisterWindowMessage( PChar( 'Message.' + Identifier ) );
45006 if JustOneMsg = 0 then Exit;
45008 Result := JustOne( Wnd, Identifier );
45009 if not Result then
45010 begin
45011 // Send a message to the first instance of applet
45013 //Wnd.CreateVisible := False;
45014 OldCap := Wnd.Caption;
45015 Wnd.Caption := GetCommandLine;
45016 if Wnd.GetWindowHandle <> 0 then
45017 begin
45018 Recipients := BSM_APPLICATIONS;
45019 BroadcastSystemMessage( BSF_QUERY or BSF_IGNORECURRENTTASK, @Recipients,
45020 JustOneMsg, 0, Wnd.fHandle );
45021 end;
45022 Wnd.Caption := OldCap;
45024 else
45025 begin
45026 // Store event handler to notify this instance about another
45027 // instance staring:
45028 OnAnotherInstance := aOnAnotherInstance;
45029 //Wnd.fWndProcJustOne := WndProcJustOneNotify;
45030 Wnd.AttachProc( WndProcJustOneNotify );
45033 if JustOneNotifier = nil then
45034 JustOneNotifier := ZJustOneNotifier.Create;
45036 end;
45037 end;
45038 {$ENDIF ASM_VERSION}
45039 //[END JustOneNotify]
45042 ///////////////////////////////////////// STRING LIST OBJECT /////////////////
45044 { TStrList }
45046 //[function NewStrList]
45047 function NewStrList: PStrList;
45048 begin
45050 New( Result, Create );
45052 {++}(*
45053 Result := PStrList.Create;
45054 *){--}
45055 end;
45056 //[END NewStrList]
45058 {$IFDEF ASM_VERSION}
45059 //[destructor TStrList.Destroy]
45060 destructor TStrList.Destroy;
45062 PUSH EAX
45063 CALL Clear
45064 POP EAX
45065 CALL TObj.Destroy
45066 end;
45067 {$ELSE ASM_VERSION} //Pascal
45068 destructor TStrList.Destroy;
45069 begin
45070 Clear;
45071 inherited;
45072 end;
45073 {$ENDIF ASM_VERSION}
45075 //[procedure TStrList.Init]
45076 procedure TStrList.Init;
45077 begin
45078 //inherited;
45079 fNameDelim := DefaultNameDelimiter;
45080 end;
45082 {$IFDEF ASM_VERSION}
45083 //[function TStrList.Add]
45084 function TStrList.Add(const S: string): integer;
45086 MOV ECX, EDX
45087 MOV EDX, [EAX].fCount
45088 PUSH EDX
45089 CALL Insert
45090 POP EAX
45091 end;
45092 {$ELSE ASM_VERSION} //Pascal
45093 function TStrList.Add(const S: string): integer;
45094 begin
45095 Result := fCount;
45096 Insert( Result, S );
45097 end;
45098 {$ENDIF ASM_VERSION}
45100 {$IFDEF ASM_VERSION}
45101 //[procedure TStrList.AddStrings]
45102 procedure TStrList.AddStrings(Strings: PStrList);
45104 PUSH EAX
45105 XCHG EAX, EDX
45106 PUSH 0
45107 MOV EDX, ESP
45108 CALL GetTextStr
45109 POP EDX
45110 POP EAX
45111 MOV CL, 1
45112 PUSH EDX
45113 CALL SetText
45114 CALL RemoveStr
45115 end;
45116 {$ELSE ASM_VERSION} //Pascal
45117 procedure TStrList.AddStrings(Strings: PStrList);
45118 begin
45119 SetText( Strings.Text, True );
45120 end;
45121 {$ENDIF ASM_VERSION}
45123 {$IFDEF ASM_VERSION}
45124 //[function TStrList.AppendToFile]
45125 function TStrList.AppendToFile(const FileName: string): Boolean;
45127 PUSH EBX
45128 MOV EBX, EDX
45129 PUSH 0
45130 MOV EDX, ESP
45131 CALL GetTextStr
45132 XCHG EAX, EBX
45133 MOV EDX, ofOpenWrite or ofOpenAlways
45134 CALL FileCreate
45135 MOV EBX, EAX
45136 INC EAX
45137 JZ @@exit
45138 DEC EAX
45139 XOR EDX, EDX
45140 XOR ECX, ECX
45141 MOV CL, spEnd
45142 CALL FileSeek
45143 POP EAX
45144 PUSH EAX
45145 CALL System.@LStrLen
45146 XCHG ECX, EAX
45147 MOV EAX, EBX
45148 POP EDX
45149 PUSH EDX
45150 CALL FileWrite
45151 XCHG EAX, EBX
45152 CALL FileClose
45153 @@exit:
45154 CALL RemoveStr
45155 POP EBX
45156 end;
45157 {$ELSE ASM_VERSION} //Pascal
45158 function TStrList.AppendToFile(const FileName: string): Boolean;
45159 var F: HFile;
45160 Buf: String;
45161 L: Integer;
45162 begin
45163 F := FileCreate( FileName, ofOpenWrite or ofOpenAlways );
45164 Result := F <> INVALID_HANDLE_VALUE;
45165 if Result then
45166 begin
45167 FileSeek( F, 0, spEnd );
45168 Buf := Text;
45169 L := Length( Buf );
45170 FileWrite( F, Buf[ 1 ], L );
45171 FileClose( F );
45172 end;
45173 end;
45174 {$ENDIF ASM_VERSION}
45176 {$IFDEF ASM_VERSION}
45177 //[procedure TStrList.Assign]
45178 procedure TStrList.Assign(Strings: PStrList);
45180 PUSHAD
45181 CALL Clear
45182 POPAD
45183 JMP AddStrings
45184 end;
45185 {$ELSE ASM_VERSION} //Pascal
45186 procedure TStrList.Assign(Strings: PStrList);
45187 begin
45188 Clear;
45189 AddStrings( Strings );
45190 end;
45191 {$ENDIF ASM_VERSION}
45193 {$IFDEF ASM_VERSION}
45194 //[procedure TStrList.Clear]
45195 procedure TStrList.Clear;
45197 PUSH EBX
45198 XCHG EBX, EAX
45199 MOV EDX, [EBX].fCount
45200 @@loo: DEC EDX
45201 JL @@eloo
45202 PUSH EDX
45203 MOV EAX, EBX
45204 CALL Delete
45205 POP EDX
45206 JMP @@loo
45207 @@eloo:
45208 XOR EAX, EAX
45209 MOV [EBX].fTextSiz, EAX
45210 XCHG EAX, [EBX].fTextBuf
45211 TEST EAX, EAX
45212 JZ @@1
45213 CALL System.@FreeMem
45214 //XOR EAX, EAX // not needed: if OK, EAX = 0
45215 @@1: XCHG EAX, [EBX].fList
45216 CALL TObj.Free
45217 POP EBX
45218 end;
45219 {$ELSE ASM_VERSION} //Pascal
45220 procedure TStrList.Clear;
45221 var I: Integer;
45222 begin
45223 if fCount > 0 then
45224 for I := fList.Count - 1 downto 0 do
45225 Delete( I );
45226 fList.Free;
45227 fList := nil;
45228 fCount := 0;
45229 if fTextBuf <> nil then
45230 begin
45231 FreeMem( fTextBuf );
45232 fTextBuf := nil;
45233 fTextSiz := 0;
45234 end;
45235 end;
45236 {$ENDIF ASM_VERSION}
45238 {$IFDEF ASM_VERSION}
45239 //[procedure TStrList.Delete]
45240 procedure TStrList.Delete(Idx: integer);
45242 DEC [EAX].fCount
45243 PUSH EAX
45244 MOV EAX, [EAX].fList
45245 MOV ECX, [EAX].TList.fItems
45246 PUSH dword ptr [ECX+EDX*4]
45247 CALL TList.Delete
45248 POP EAX
45249 POP EDX
45250 MOV ECX, [EDX].fTextSiz
45251 JECXZ @@fremem
45252 CMP EAX, [EDX].fTextBuf
45253 JB @@fremem
45254 ADD ECX, [EDX].fTextBuf
45255 CMP EAX, ECX
45256 JB @@exit
45257 @@fremem:
45258 CALL System.@FreeMem
45259 @@exit:
45260 end;
45261 {$ELSE ASM_VERSION} //Pascal
45262 procedure TStrList.Delete(Idx: integer);
45263 var P: DWORD;
45264 El:Pointer;
45265 begin
45266 P := DWORD( fList.fItems[ Idx ] );
45267 if (fTextBuf <> nil) and ( P >= DWORD( fTextBuf )) and
45268 ( P < DWORD( fTextBuf ) + fTextSiz ) then
45269 else
45270 begin
45271 El := FList.Items[ Idx ];
45272 FreeMem( El );
45273 end;
45274 fList.Delete( Idx );
45275 Dec( fCount );
45276 end;
45277 {$ENDIF ASM_VERSION}
45279 {$IFDEF ASM_VERSION}
45280 //[function TStrList.Get]
45281 function TStrList.Get(Idx: integer): string;
45283 PUSH ECX
45284 MOV EAX, [EAX].fList
45285 TEST EAX, EAX
45286 JZ @@1
45287 CALL TList.Get
45288 @@1: XCHG EDX, EAX
45289 POP EAX
45290 JMP System.@LStrFromPChar
45291 end;
45292 {$ELSE ASM_VERSION} //Pascal
45293 function TStrList.Get(Idx: integer): string;
45294 begin
45295 if fList <> nil then
45296 Result := PChar( fList.Items[ Idx ] )
45297 else Result := '';
45298 end;
45299 {$ENDIF ASM_VERSION}
45301 {$IFDEF ASM_VERSION}
45302 //[function TStrList.GetPChars]
45303 function TStrList.GetPChars(Idx: Integer): PChar;
45305 MOV EAX, [EAX].fList
45306 MOV EAX, [EAX].TList.fItems
45307 MOV EAX, [EAX+EDX*4]
45308 end;
45309 {$ELSE ASM_VERSION} //Pascal
45310 function TStrList.GetPChars(Idx: Integer): PChar;
45311 begin
45312 Result := PChar( fList.fItems[ Idx ] );
45313 end;
45314 {$ENDIF ASM_VERSION}
45316 {$IFDEF ASM_VERSION}
45317 //[function TStrList.GetTextStr]
45318 function TStrList.GetTextStr: string;
45320 PUSH ESI
45321 PUSH EDI
45322 MOV ECX, [EAX].fCount
45323 MOV EAX, [EAX].fList
45324 PUSH ECX
45325 JECXZ @@1
45326 MOV ESI, [EAX].TList.fItems
45327 @@1: PUSH ESI
45328 XCHG EAX, EDX
45329 XOR EDX, EDX
45330 JECXZ @@10
45331 PUSH EAX
45332 @@loo1:
45333 PUSH ECX
45334 PUSH EDX
45335 LODSD
45336 CALL StrLen
45337 POP EDX
45338 LEA EDX, [EDX+EAX+2]
45339 POP ECX
45340 LOOP @@loo1
45342 POP EAX
45343 POP ESI
45344 XCHG ECX, EDX
45345 PUSH EAX
45346 @@10:
45347 {$IFDEF _D2}
45348 CALL _LStrFromPCharLen
45349 {$ELSE}
45350 CALL System.@LStrFromPCharLen
45351 {$ENDIF}
45353 POP EDI
45354 POP ECX
45355 JECXZ @@exit
45356 MOV EDI, [EDI]
45358 @@loo2: PUSH ECX
45359 LODSD
45360 PUSH EAX
45361 CALL StrLen
45362 XCHG ECX, EAX
45363 POP EAX
45364 XCHG EAX, ESI
45365 REP MOVSB
45366 XCHG ESI, EAX
45367 MOV AX, $0A0D
45368 STOSW
45369 POP ECX
45370 LOOP @@loo2
45372 XCHG EAX, ECX
45373 STOSB
45374 @@exit:
45375 POP EDI
45376 POP ESI
45377 end;
45378 {$ELSE ASM_VERSION} //Pascal
45379 function TStrList.GetTextStr: string;
45381 I, Len, Size: integer;
45382 P: PChar;
45383 begin
45384 Size := 0;
45386 for I := 0 to fCount - 1 do
45387 Inc(Size, StrLen( PChar(fList.fItems[I]) ) + 2);
45389 SetString(Result, nil, Size);
45391 P := Pointer(Result);
45392 for I := 0 to Count - 1 do
45393 begin
45394 Len := StrLen(PChar(fList.fItems[I]));
45395 if (Len > 0) then
45396 begin
45397 System.Move(PChar(fList.fItems[I])^, P^, Len);
45398 Inc(P, Len);
45399 end;
45400 P^ := #13;
45401 Inc(P);
45402 P^ := #10;
45403 Inc(P);
45404 end;
45405 end;
45406 {$ENDIF ASM_VERSION}
45408 {$IFDEF ASM_VERSION}
45409 //[function TStrList.IndexOf]
45410 function TStrList.IndexOf(const S: string): integer;
45412 PUSH EBX
45413 PUSH ESI
45414 OR EBX, -1
45415 MOV ECX, [EAX].fCount
45416 JECXZ @@exit
45417 MOV ESI, [EAX].fList
45418 MOV ESI, [ESI].TList.fItems
45419 @@loo: LODSD
45420 INC EBX
45421 CMP EAX, EDX
45422 JE @@exit
45423 OR EDX, EDX
45424 JZ @@1
45425 PUSH EDX
45426 PUSH ECX
45427 CALL StrComp
45428 POP ECX
45429 POP EDX
45430 JE @@exit
45431 @@1: LOOP @@loo
45432 OR EBX, -1
45433 @@exit: XCHG EAX, EBX
45434 POP ESI
45435 POP EBX
45436 end;
45437 {$ELSE ASM_VERSION} //Pascal
45438 function TStrList.IndexOf(const S: string): integer;
45439 begin
45440 for Result := 0 to fCount - 1 do
45441 if (S = PChar( fList.Items[Result] )) then Exit;
45442 Result := -1;
45443 end;
45444 {$ENDIF ASM_VERSION}
45446 //[function TStrList.IndexOf]
45447 function TStrList.IndexOf_NoCase(const S: string): integer;
45448 begin
45449 for Result := 0 to fCount - 1 do
45450 if StrComp_NoCase( PChar( S ), PChar( fList.Items[Result] ) ) = 0 then Exit;
45451 Result := -1;
45452 end;
45454 function TStrList.IndexOfStrL_NoCase( Str: PChar; L: Integer ): integer;
45455 begin
45456 for Result := 0 to fCount - 1 do
45457 if (StrLen( PChar( fList.fItems[ Result ] ) ) = DWORD( L )) and
45458 (StrLComp_NoCase( Str, PChar( fList.fItems[ Result ] ), L ) = 0) then Exit;
45459 Result := -1;
45460 end;
45462 //[function TStrList.Find]
45463 function TStrList.Find(const S: String; var Index: Integer): Boolean;
45465 L, H, I, C: Integer;
45466 begin
45467 Result := FALSE;
45468 L := 0;
45469 H := FCount - 1;
45470 while L <= H do
45471 begin
45472 I := (L + H) shr 1;
45473 C := AnsiCompareStr( PChar( fList.Items[ I ] ), S );
45474 if C < 0 then L := I + 1 else
45475 begin
45476 H := I - 1;
45477 if C = 0 then
45478 begin
45479 Result := TRUE;
45480 L := I;
45481 //break;
45482 //if Duplicates <> dupAccept then L := I;
45483 end;
45484 end;
45485 end;
45486 Index := L;
45487 end;
45489 {$IFDEF ASM_VERSION}
45490 //[procedure TStrList.Insert]
45491 procedure TStrList.Insert(Idx: integer; const S: string);
45493 PUSH EBX
45494 PUSH EDX
45495 PUSH ECX
45496 XCHG EBX, EAX
45497 MOV EAX, [EBX].fList
45498 TEST EAX, EAX
45499 JNZ @@1
45500 CALL NewList
45501 MOV [EBX].fList, EAX
45502 @@1:
45503 POP EAX
45504 PUSH EAX // push S
45505 CALL System.@LStrLen
45506 INC EAX
45507 PUSH EAX // push L
45508 CALL System.@GetMem
45509 MOV byte ptr[EAX], 0
45510 XCHG EDX, EAX
45511 POP ECX
45512 POP EAX
45513 PUSH EDX // push Mem
45514 TEST EAX, EAX
45515 JE @@2
45516 CALL System.Move
45517 @@2: POP ECX
45518 POP EDX
45519 MOV EAX, [EBX].fList
45520 CALL TList.Insert
45521 INC [EBX].fCount
45522 POP EBX
45523 end;
45524 {$ELSE ASM_VERSION} //Pascal
45525 procedure TStrList.Insert(Idx: integer; const S: string);
45526 var Mem: PChar;
45527 L: Integer;
45528 begin
45529 if fList = nil then
45530 fList := NewList;
45531 L := Length( S ) + 1;
45532 GetMem( Mem, L );
45533 Mem[0] := #0;
45534 if L > 1 then
45535 System.Move( S[1], Mem[0], L );
45536 fList.Insert( Idx, Mem );
45537 Inc( fCount );
45538 end;
45539 {$ENDIF ASM_VERSION}
45541 {$IFDEF ASM_VERSION}
45542 //[function TStrList.LoadFromFile]
45543 function TStrList.LoadFromFile(const FileName: string): Boolean;
45545 PUSH EAX
45546 XCHG EAX, EDX
45547 MOV EDX, ofOpenRead or ofShareDenyWrite or ofOpenExisting
45548 CALL FileCreate
45549 INC EAX
45550 JZ @@exit
45551 DEC EAX
45552 PUSH EBX
45553 XCHG EBX, EAX
45554 PUSH 0
45555 PUSH EBX
45556 CALL GetFileSize
45557 XOR EDX, EDX
45558 PUSH EDX
45559 XCHG ECX, EAX
45560 MOV EAX, ESP
45561 PUSH ECX
45562 {$IFDEF _D2}
45563 CALL _LStrFromPCharLen
45564 {$ELSE}
45565 CALL System.@LStrFromPCharLen
45566 {$ENDIF}
45567 POP ECX
45568 MOV EAX, EBX
45569 POP EDX
45570 PUSH EDX
45571 CALL FileRead
45572 XCHG EAX, EBX
45573 CALL FileClose
45574 POP EDX
45575 POP EBX
45576 POP EAX
45577 PUSH EDX
45578 XOR ECX, ECX
45579 CALL SetText
45580 CALL RemoveStr
45581 PUSH EDX
45582 MOV AL, 1
45583 @@exit: POP EDX
45584 end;
45585 {$ELSE ASM_VERSION} //Pascal
45586 function TStrList.LoadFromFile(const FileName: string): Boolean;
45587 var Buf: String;
45588 F: HFile;
45589 Sz: Integer;
45590 begin
45591 F := FileCreate( FileName, ofOpenRead or ofShareDenyWrite or ofOpenExisting );
45592 Result := F <> INVALID_HANDLE_VALUE;
45593 if Result then
45594 begin
45595 Sz := GetFileSize( F, nil );
45596 SetString( Buf, nil, Sz );
45597 FileRead( F, Buf[1], Sz );
45598 FileClose( F );
45600 SetText( Buf, False );
45601 end;
45602 end;
45603 {$ENDIF ASM_VERSION}
45605 {$IFDEF ASM_VERSION}
45606 //[procedure TStrList.LoadFromStream]
45607 procedure TStrList.LoadFromStream(Stream: PStream; Append2List: boolean);
45609 PUSH EAX
45610 PUSH ECX
45611 PUSH EBX
45612 XCHG EAX, EDX
45613 MOV EBX, EAX
45614 CALL TStream.GetSize
45615 PUSH EAX
45616 MOV EAX, EBX
45617 CALL TStream.GetPosition
45618 POP ECX
45619 SUB ECX, EAX
45620 XOR EDX, EDX
45621 PUSH EDX
45622 MOV EAX, ESP
45623 PUSH ECX
45624 {$IFDEF _D2}
45625 CALL _LStrFromPCharLen
45626 {$ELSE}
45627 CALL System.@LStrFromPCharLen
45628 {$ENDIF}
45629 POP ECX
45630 POP EDX
45631 XCHG EAX, EBX
45632 PUSH EDX
45633 CALL TStream.Read
45634 POP EDX
45635 POP EBX
45636 POP ECX
45637 POP EAX
45638 PUSH EDX
45639 CALL SetText
45640 CALL RemoveStr
45641 end;
45642 {$ELSE ASM_VERSION} //Pascal
45643 procedure TStrList.LoadFromStream(Stream: PStream; Append2List: boolean);
45644 var Buf: String;
45645 Sz: Integer;
45646 begin
45647 Sz := Stream.Size - Stream.Position;
45648 SetString( Buf, nil, Sz );
45649 Stream.Read( Buf[1], Sz );
45650 SetText( Buf, Append2List );
45651 end;
45652 {$ENDIF ASM_VERSION}
45654 {$IFDEF ASM_VERSION}
45655 //[procedure TStrList.MergeFromFile]
45656 procedure TStrList.MergeFromFile(const FileName: string);
45658 PUSH EAX
45659 XCHG EAX, EDX
45660 CALL NewReadFileStream
45661 XCHG EDX, EAX
45662 POP EAX
45663 MOV CL, 1
45664 PUSH EDX
45665 CALL LoadFromStream
45666 POP EAX
45667 JMP TObj.Free
45668 end;
45669 {$ELSE ASM_VERSION} //Pascal
45670 procedure TStrList.MergeFromFile(const FileName: string);
45671 var TmpStream: PStream;
45672 begin
45673 TmpStream := NewReadFileStream( FileName );
45674 LoadFromStream( TmpStream, True );
45675 TmpStream.Free;
45676 end;
45677 {$ENDIF ASM_VERSION}
45679 //[procedure TStrList.Move]
45680 procedure TStrList.Move(CurIndex, NewIndex: integer);
45681 begin
45682 fList.MoveItem( CurIndex, NewIndex );
45683 end;
45685 {$IFDEF ASM_VERSION}
45686 //[procedure TStrList.Put]
45687 procedure TStrList.Put(Idx: integer; const Value: string);
45689 PUSH EAX
45690 PUSH EDX
45691 CALL Insert
45692 POP EDX
45693 POP EAX
45694 INC EDX
45695 JMP Delete
45696 end;
45697 {$ELSE ASM_VERSION} //Pascal
45698 procedure TStrList.Put(Idx: integer; const Value: string);
45699 begin
45700 Delete( Idx );
45701 Insert( Idx, Value );
45702 end;
45703 {$ENDIF ASM_VERSION}
45705 {$IFDEF ASM_VERSION}
45706 //[function TStrList.SaveToFile]
45707 function TStrList.SaveToFile(const FileName: string): Boolean;
45709 PUSH EBX
45710 PUSH EAX
45711 XCHG EAX, EDX
45712 MOV EDX, ofOpenWrite or ofOpenAlways
45713 CALL FileCreate
45714 INC EAX
45715 JZ @@exit
45716 DEC EAX
45717 XCHG EBX, EAX
45718 POP EAX
45719 PUSH 0
45720 MOV EDX, ESP
45721 CALL GetTextStr
45722 POP EAX
45723 PUSH EAX
45724 CALL System.@LStrLen
45725 XCHG ECX, EAX
45726 POP EDX
45727 PUSH EDX
45728 MOV EAX, EBX
45729 CALL FileWrite
45730 PUSH EBX
45731 CALL SetEndOfFile
45732 XCHG EAX, EBX
45733 CALL FileClose
45734 CALL RemoveStr
45735 PUSH EDX
45736 INC EAX
45737 @@exit:
45738 POP EDX
45739 POP EBX
45740 end;
45741 {$ELSE ASM_VERSION} //Pascal
45742 function TStrList.SaveToFile(const FileName: string): Boolean;
45743 var F: HFile;
45744 Buf: String;
45745 begin
45746 F := FileCreate( FileName, ofOpenWrite or ofOpenAlways );
45747 Result := F <> INVALID_HANDLE_VALUE;
45748 if Result then
45749 begin
45750 Buf := Text;
45751 FileWrite( F, Buf[ 1 ], Length( Buf ) );
45752 SetEndOfFile( F ); // necessary! - V.K.
45753 FileClose( F );
45754 end;
45755 end;
45756 {$ENDIF ASM_VERSION}
45758 {$IFDEF ASM_VERSION}
45759 //[procedure TStrList.SaveToStream]
45760 procedure TStrList.SaveToStream(Stream: PStream);
45762 PUSH EDX
45763 PUSH 0
45764 MOV EDX, ESP
45765 CALL GetTextStr
45766 POP EAX
45767 PUSH EAX
45768 CALL System.@LStrLen
45769 XCHG ECX, EAX
45770 POP EDX
45771 POP EAX
45772 PUSH EDX
45773 JECXZ @@1
45774 CALL TStream.Write
45775 @@1:
45776 CALL RemoveStr
45777 end;
45778 {$ELSE ASM_VERSION} //Pascal
45779 procedure TStrList.SaveToStream(Stream: PStream);
45780 var S: string;
45781 L: Integer;
45782 begin
45783 S := GetTextStr;
45784 L := Length( S );
45785 if L <> 0 then
45786 Stream.Write( S[1], L );
45787 end;
45788 {$ENDIF ASM_VERSION}
45790 {$IFDEF ASM_VERSION}
45791 //[procedure TStrList.SetText]
45792 procedure TStrList.SetText(const S: string; Append2List: boolean);
45794 DEC CL
45795 JZ @@1
45796 PUSHAD
45797 CALL Clear
45798 POPAD
45799 @@1: CALL EDX2PChar
45800 JZ @@exit
45802 PUSH EBX
45803 PUSH EDI
45804 MOV EBX, EAX
45805 MOV EDI, [EBX].fTextSiz
45807 MOV EAX, [EDX-4] // EAX = Length(S)
45808 INC EAX
45809 PUSH EAX
45811 // add S to text buffer
45812 //CMP byte ptr [EDX], 0
45813 //JZ @@eatb
45815 PUSH EDX
45816 PUSH [EBX].fTextBuf
45817 ADD EAX, [EBX].fTextSiz
45818 CALL System.@GetMem
45819 MOV [EBX].fTextBuf, EAX
45821 MOV ECX, EDI
45822 XCHG EDX, EAX
45823 POP EAX
45824 JECXZ @@atb_fin
45825 PUSH EAX
45826 CALL System.Move
45828 POP EDX
45829 PUSH EDX
45831 PUSH ESI
45832 MOV ESI, [EBX].fList
45833 MOV ESI, [ESI].TList.fItems
45834 MOV ECX, [EBX].fCount
45836 @@atb_loo:
45837 LODSD
45838 SUB EAX, EDX
45839 CMP EAX, [EBX].fTextSiz
45840 JAE @@atb_nxt
45842 ADD EAX, [EBX].fTextBuf
45843 MOV [ESI-4], EAX
45845 @@atb_nxt: LOOP @@atb_loo
45847 POP ESI
45848 POP EAX
45849 CALL System.@FreeMem
45850 @@atb_fin:
45851 POP EAX
45853 MOV EDX, EDI
45854 ADD EDX, [EBX].fTextBuf
45855 POP ECX
45856 PUSH ECX
45857 ADD [EBX].fTextSiz, ECX
45859 CALL System.Move
45861 @@eatb:
45862 ADD EDI, [EBX].fTextBuf // EDI ~ P
45864 MOV ECX, [EBX].fList
45865 INC ECX
45866 LOOP @@2
45867 CALL NewList
45868 MOV [EBX].fList, EAX
45869 @@2:
45870 POP ECX
45871 MOV EDX, [EBX].fCount
45873 PUSH EDI
45874 PUSH ECX
45875 MOV AL, $0D
45877 @@loo1: CMP byte ptr [EDI], 0
45878 JZ @@eloo1
45880 INC EDX
45881 REPNZ SCASB
45882 JNZ @@eloo1
45884 CMP byte ptr [EDI], $0A
45885 JNZ @@loo1
45886 INC EDI
45887 LOOP @@loo1
45889 @@eloo1:
45890 MOV [EBX].fCount, EDX
45891 MOV EAX, [EBX].fList
45892 PUSH EDX
45893 PUSH EAX
45894 CMP EDX, [EAX].TList.fCapacity
45895 JLE @@3
45896 CALL TList.SetCapacity
45897 @@3: POP EAX
45898 POP ECX
45900 XCHG ECX, [EAX].TList.fCount
45901 MOV EDX, [EAX].TList.fItems
45902 LEA EDX, [EDX+ECX*4]
45904 POP ECX
45905 POP EDI
45907 MOV EAX, $0D
45908 @@loo2: CMP byte ptr [EDI], AH
45909 JZ @@eloo2
45911 MOV [EDX], EDI
45912 ADD EDX, 4
45914 REPNZ SCASB
45915 JNZ @@eloo2
45917 MOV [EDI-1], AH
45919 CMP byte ptr [EDI], $0A
45920 JNZ @@loo2
45921 INC EDI
45922 LOOP @@loo2
45923 @@eloo2:
45925 POP EDI
45926 POP EBX
45927 @@exit:
45928 end;
45929 {$ELSE ASM_VERSION} //Pascal
45930 //[procedure TStrList.SetText]
45931 procedure TStrList.SetText(const S: string; Append2List: boolean);
45933 P, TheLast : PChar;
45934 L, I : Integer;
45936 procedure AddTextBuf(Src: PChar; Len: DWORD);
45937 var OldTextBuf, P: PChar;
45938 I : Integer;
45939 begin
45940 if Src <> nil then
45941 begin
45942 OldTextBuf := fTextBuf;
45943 GetMem( fTextBuf, fTextSiz + Len );
45944 if fTextSiz <> 0 then
45945 begin
45946 System.Move( OldTextBuf^, fTextBuf^, fTextSiz );
45947 for I := 0 to fCount - 1 do
45948 begin
45949 P := fList.fItems[ I ];
45950 if (DWORD( P ) >= DWORD( OldTextBuf )) and
45951 (DWORD( P ) < DWORD( OldTextBuf ) + fTextSiz) then
45952 fList.fItems[ I ] := Pointer( DWORD( P ) - DWORD( OldTextBuf ) + DWORD( fTextBuf ) );
45953 end;
45954 FreeMem( OldTextBuf );
45955 end;
45956 System.Move( Src^, fTextBuf[ fTextSiz ], Len );
45957 Inc( fTextSiz, Len );
45958 end;
45959 end;
45961 begin
45962 if not Append2List then Clear;
45963 if S = '' then Exit;
45965 L := fTextSiz;
45966 AddTextBuf( PChar( S ), Length( S ) + 1 );
45968 P := PChar( DWORD( fTextBuf ) + DWORD( L ) );
45969 if fList = nil then
45970 fList := NewList;
45972 I := 0;
45973 TheLast := P + Length( S );
45974 while P^ <> #0 do
45975 begin
45976 Inc( I );
45977 P := StrScanLen( P, #13, TheLast - P );
45978 if P^ = #10 then
45979 Inc( P );
45980 end;
45982 Inc( fCount, I );
45983 if fList.fCapacity < fCount then
45984 fList.Capacity := fCount;
45986 P := PChar( DWORD( fTextBuf ) + DWORD( L ) );
45987 while P^ <> #0 do
45988 begin
45989 fList.Add( P );
45990 P := StrScanLen( P, #13, TheLast - P );
45991 if PChar( P - 1 )^ = #13 then
45992 PChar( P - 1 )^ := #0;
45993 if P^ = #10 then Inc(P);
45994 end;
45995 end;
45996 {$ENDIF ASM_VERSION}
45998 //[procedure TStrList.SetUnixText]
45999 procedure TStrList.SetUnixText(const S: String; Append2List: Boolean);
46000 var S1: String;
46001 begin
46002 S1 := S;
46003 NormalizeUnixText( S1 );
46004 SetText( S1, Append2List );
46005 end;
46007 //[procedure TStrList.SetTextStr]
46008 procedure TStrList.SetTextStr(const Value: string);
46009 begin
46010 SetText( Value, False );
46011 end;
46013 //[PROCEDURE LowerCaseStrFromPCharEDX]
46014 {$IFDEF ASM_VERSION}
46015 procedure LowerCaseStrFromPCharEDX;
46017 { <- EDX = PChar string
46018 -> [ESP] = LowerCase( PChar( EDX ) ),
46019 EAX, EDX, ECX - ?
46021 POP EAX
46022 PUSH 0
46023 PUSH EAX
46024 LEA EAX, [ESP+4]
46025 PUSH EAX
46026 CALL System.@LStrFromPChar
46027 POP EDX
46028 MOV EAX, [EDX]
46029 JMP LowerCase
46030 end;
46031 {$ENDIF ASM_VERSION}
46032 //[END LowerCaseStrFromPCharEDX]
46034 //[FUNCTION CompareStrListItems]
46035 {$IFDEF ASM_VERSION}
46036 function CompareStrListItems( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;
46038 CMP [EAX].TStrList.fCaseSensitiveSort, 0
46039 MOV EAX, [EAX].TStrList.fList
46040 MOV EAX, [EAX].TList.fItems
46041 MOV EDX, [EAX+EDX*4]
46042 MOV EAX, [EAX+ECX*4]
46043 XCHG EAX, EDX
46044 JNZ StrComp
46045 PUSH EBX
46047 XCHG EBX, EAX
46048 CALL LowerCaseStrFromPCharEDX
46050 MOV EDX, EBX
46051 CALL LowerCaseStrFromPCharEDX
46053 POP EAX
46054 POP EDX
46055 PUSH EDX
46056 PUSH EAX
46057 CALL EAX2PChar
46058 CALL EDX2PChar
46059 CALL StrComp
46060 XCHG EBX, EAX
46062 CALL RemoveStr
46063 CALL RemoveStr
46065 XCHG EAX, EBX
46066 POP EBX
46067 end;
46068 {$ELSE ASM_VERSION} //Pascal
46069 function CompareStrListItems( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;
46070 var S1, S2 : PChar;
46071 begin
46072 S1 := PStrList( Sender ).fList.Items[ e1 ];
46073 S2 := PStrList( Sender ).fList.Items[ e2 ];
46074 if PStrList( Sender ).fCaseSensitiveSort then
46075 Result := StrComp( S1, S2 )
46076 else
46077 Result := StrComp( PChar( LowerCase( S1 ) ), PChar( LowerCase( S2 ) ) );
46078 end;
46079 {$ENDIF ASM_VERSION}
46080 //[END CompareStrListItems]
46082 //[FUNCTION CompareAnsiStrListItems]
46083 {$IFDEF ASM_VERSION}
46084 function CompareAnsiStrListItems( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;
46086 CMP byte ptr [EAX].TStrList.fCaseSensitiveSort, 0
46087 MOV EAX, [EAX].TStrList.fList
46088 MOV EAX, [EAX].TList.fItems
46089 MOV EDX, [EAX+EDX*4]
46090 MOV EAX, [EAX+ECX*4]
46091 XCHG EAX, EDX
46092 JZ _AnsiCompareStrNoCase
46093 JMP _AnsiCompareStr
46094 end;
46095 {$ELSE ASM_VERSION} //Pascal
46096 function CompareAnsiStrListItems( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;
46097 var S1, S2 : PChar;
46098 begin
46099 S1 := PStrList( Sender ).fList.Items[ e1 ];
46100 S2 := PStrList( Sender ).fList.Items[ e2 ];
46101 if PStrList( Sender ).fCaseSensitiveSort then
46102 Result := _AnsiCompareStr( S1, S2 )
46103 else
46104 Result := _AnsiCompareStrNoCase( S1, S2 );
46105 end;
46106 {$ENDIF ASM_VERSION}
46107 //[END CompareAnsiStrListItems]
46109 {$IFNDEF ASM_VERSION}
46110 //[procedure SwapStrListItems]
46111 procedure SwapStrListItems( const Sender: Pointer; const e1, e2: DWORD );
46112 begin
46113 PStrList( Sender ).Swap( e1, e2 );
46114 end;
46115 {$ENDIF}
46117 {$IFDEF ASM_VERSION}
46118 //[procedure TStrList.Sort]
46119 procedure TStrList.Sort(CaseSensitive: Boolean);
46121 MOV [EAX].fCaseSensitiveSort, DL
46122 PUSH Offset[TStrList.Swap]
46123 MOV ECX, Offset[CompareStrListItems]
46124 MOV EDX, [EAX].fCount
46125 CALL SortData
46126 end;
46127 {$ELSE ASM_VERSION} //Pascal
46128 procedure TStrList.Sort(CaseSensitive: Boolean);
46129 begin
46130 fCaseSensitiveSort := CaseSensitive;
46131 SortData( @Self, fCount, @CompareStrListItems, @SwapStrListItems );
46132 end;
46133 {$ENDIF ASM_VERSION}
46135 {$IFDEF ASM_VERSION}
46136 //[procedure TStrList.AnsiSort]
46137 procedure TStrList.AnsiSort(CaseSensitive: Boolean);
46139 MOV [EAX].fCaseSensitiveSort, DL
46140 PUSH Offset[TStrList.Swap]
46141 MOV ECX, Offset[CompareAnsiStrListItems]
46142 MOV EDX, [EAX].fCount
46143 CALL SortData
46144 end;
46145 {$ELSE ASM_VERSION} //Pascal
46146 procedure TStrList.AnsiSort(CaseSensitive: Boolean);
46147 begin
46148 fCaseSensitiveSort := CaseSensitive;
46149 SortData( @Self, fCount, @CompareAnsiStrListItems, @SwapStrListItems );
46150 end;
46151 {$ENDIF ASM_VERSION}
46153 //[procedure TStrList.Swap]
46154 procedure TStrList.Swap(Idx1, Idx2: Integer);
46155 begin
46156 fList.Swap( Idx1, Idx2 );
46157 end;
46159 //[function TStrList.Last]
46160 function TStrList.Last: String;
46161 begin
46162 if Count = 0 then
46163 Result := ''
46164 else
46165 Result := Items[ Count - 1 ];
46166 end;
46168 //-- code by Dod:
46169 //[function TStrList.IndexOfName]
46170 function TStrList.IndexOfName(Name: string): Integer;
46172 i: Integer;
46173 L: Integer;
46174 begin
46175 Result:=-1;
46176 // Do not start search if empty string
46177 L := Length( Name );
46178 if L > 0 then
46179 begin
46180 Name := LowerCase( Name ) + fNameDelim;
46181 Inc( L );
46182 for i := 0 to fCount - 1 do
46183 begin
46184 // For optimization, check only list entry that begin with same letter as searched name
46185 if StrLComp( PChar( LowerCase( ItemPtrs[ i ] ) ), PChar( Name ), L ) = 0 then
46186 begin
46187 Result:=i;
46188 exit;
46189 end;
46190 end;
46191 end;
46192 end;
46194 //-- code by Dod:
46195 //[function TStrList.GetValue]
46196 function TStrList.GetValue(const Name: string): string;
46198 i: Integer;
46199 begin
46200 I := IndexOfName(Name);
46201 if I >= 0
46202 then Result := Copy(Items[i], Length(Name) + 2, Length(Items[i])-Length(Name)-1)
46203 else Result := '';
46204 end;
46206 //-- code by Dod:
46207 //[procedure TStrList.SetValue]
46208 procedure TStrList.SetValue(const Name, Value: string);
46210 I: Integer;
46211 begin
46212 I := IndexOfName(Name);
46213 if i=-1
46214 then Add( Name + fNameDelim + Value )
46215 else Items[i] := Name + fNameDelim + Value;
46216 end;
46218 //[function TStrList.GetLineName]
46219 function TStrList.GetLineName(Idx: Integer): string;
46220 begin
46221 Result := Items[ Idx ];
46222 Result := Parse( Result, fNameDelim );
46223 end;
46225 //[procedure TStrList.SetLineName]
46226 procedure TStrList.SetLineName(Idx: Integer; const NV: string);
46227 begin
46228 Items[ Idx ] := NV + fNameDelim + LineValue[ Idx ];
46229 end;
46231 //[function TStrList.GetLineValue]
46232 function TStrList.GetLineValue(Idx: Integer): string;
46233 begin
46234 Result := Items[ Idx ];
46235 Parse( Result, fNameDelim );
46236 end;
46238 //[procedure TStrList.SetLineValue]
46239 procedure TStrList.SetLineValue(Idx: Integer; const Value: string);
46240 begin
46241 Items[ Idx ] := LineName[ Idx ] + fNameDelim + Value;
46242 end;
46244 ////////////////////////////////// EXTENDED STRING LIST OBJECT ////////////////
46246 { TStrListEx }
46248 //[function NewStrListEx]
46249 function NewStrListEx: PStrListEx;
46250 begin
46252 new( Result, Create );
46254 {++}(*
46255 Result := PStrListEx.Create;
46256 *){--}
46257 end;
46258 //[END NewStrListEx]
46260 //[destructor TStrListEx.Destroy]
46261 destructor TStrListEx.Destroy;
46262 var Obj: PList;
46263 begin
46264 Obj := FObjects;
46265 inherited;
46266 Obj.Free;
46267 end;
46269 //[function TStrListEx.GetObjects]
46270 function TStrListEx.GetObjects(Idx: Integer): DWORD;
46271 begin
46272 Result := DWORD( FObjects.Items[ Idx ] );
46273 end;
46275 //[procedure TStrListEx.SetObjects]
46276 procedure TStrListEx.SetObjects(Idx: Integer; const Value: DWORD);
46277 begin
46278 ProvideObjCapacity( Idx + 1 );
46279 FObjects.Items[ Idx ] := Pointer( Value );
46280 end;
46282 //[procedure TStrListEx.Init]
46283 procedure TStrListEx.Init;
46284 begin
46285 FObjects := NewList;
46286 end;
46288 //[procedure SwapStrListExItems]
46289 procedure SwapStrListExItems( const Sender: Pointer; const e1, e2: DWORD );
46290 begin
46291 PStrListEx( Sender ).Swap( e1, e2 );
46292 end;
46294 //[procedure TStrListEx.AnsiSort]
46295 procedure TStrListEx.AnsiSort(CaseSensitive: Boolean);
46296 begin
46297 fCaseSensitiveSort := CaseSensitive;
46298 SortData( @Self, fCount, @CompareAnsiStrListItems, @SwapStrListExItems );
46299 end;
46301 //[procedure TStrListEx.Sort]
46302 procedure TStrListEx.Sort(CaseSensitive: Boolean);
46303 begin
46304 fCaseSensitiveSort := CaseSensitive;
46305 SortData( @Self, fCount, @CompareStrListItems, @SwapStrListExItems );
46306 end;
46308 //[procedure TStrListEx.Move]
46309 procedure TStrListEx.Move(CurIndex, NewIndex: integer);
46310 begin
46311 // move string
46312 fList.MoveItem( CurIndex, NewIndex );
46313 // move object
46314 if FObjects.fCount >= Min( CurIndex, NewIndex ) then
46315 begin
46316 ProvideObjCapacity( max( CurIndex, NewIndex ) + 1 );
46317 FObjects.MoveItem( CurIndex, NewIndex );
46318 end;
46319 end;
46321 //[procedure TStrListEx.Swap]
46322 procedure TStrListEx.Swap(Idx1, Idx2: Integer);
46323 begin
46324 // swap strings
46325 fList.Swap( Idx1, Idx2 );
46326 // swap objects
46327 if FObjects.fCount >= Min( Idx1, Idx2 ) then
46328 begin
46329 ProvideObjCapacity( max( Idx1, Idx2 ) + 1 );
46330 FObjects.Swap( Idx1, Idx2 );
46331 end;
46332 end;
46334 //[procedure TStrListEx.ProvideObjCapacity]
46335 procedure TStrListEx.ProvideObjCapacity(NewCap: Integer);
46336 begin
46337 if FObjects.FCount < NewCap then
46338 begin
46339 FObjects.Capacity := NewCap;
46340 FillChar( FObjects.FItems[ FObjects.FCount ],
46341 (FObjects.Capacity - FObjects.Count) * sizeof( Pointer ), 0 );
46342 FObjects.FCount := NewCap;
46343 end;
46344 end;
46346 //[procedure TStrListEx.AddStrings]
46347 procedure TStrListEx.AddStrings(Strings: PStrListEx);
46348 var I: Integer;
46349 begin
46350 I := Count;
46351 if Strings.FObjects.fCount > 0 then
46352 ProvideObjCapacity( Count );
46353 inherited AddStrings( Strings );
46354 if Strings.FObjects.fCount > 0 then
46355 begin
46356 ProvideObjCapacity( I + Strings.FObjects.fCount );
46357 System.Move( Strings.FObjects.FItems[ 0 ],
46358 FObjects.FItems[ I ],
46359 Sizeof( Pointer ) * Strings.FObjects.fCount );
46360 end;
46361 end;
46363 //[procedure TStrListEx.Assign]
46364 procedure TStrListEx.Assign(Strings: PStrListEx);
46365 begin
46366 inherited Assign( Strings );
46367 FObjects.Assign( Strings.FObjects );
46368 end;
46370 //[procedure TStrListEx.Clear]
46371 procedure TStrListEx.Clear;
46372 begin
46373 inherited;
46374 FObjects.Clear;
46375 end;
46377 //[procedure TStrListEx.Delete]
46378 procedure TStrListEx.Delete(Idx: integer);
46379 begin
46380 inherited;
46381 if FObjects.fCount > Idx then // mdw: '>=' -> '>'
46382 FObjects.Delete( Idx );
46383 end;
46385 //[function TStrListEx.LastObj]
46386 function TStrListEx.LastObj: DWORD;
46387 begin
46388 if Count = 0 then
46389 Result := 0
46390 else
46391 Result := Objects[ Count - 1 ];
46392 end;
46394 //[function TStrListEx.AddObject]
46395 function TStrListEx.AddObject(const S: String; Obj: DWORD): Integer;
46396 begin
46397 Result := Count;
46398 InsertObject( Count, S, Obj );
46399 end;
46401 //[procedure TStrListEx.InsertObject]
46402 procedure TStrListEx.InsertObject(Before: Integer; const S: String; Obj: DWORD);
46403 begin
46404 Insert( Before, S );
46405 FObjects.Insert( Before, Pointer( Obj ) );
46406 end;
46408 //[function TStrListEx.IndexOfObj]
46409 function TStrListEx.IndexOfObj( Obj: Pointer ): Integer;
46410 begin
46411 Result := FObjects.IndexOf( Obj );
46412 end;
46415 //[function WStrLen]
46416 function WStrLen( W: PWideChar ): Integer;
46418 XCHG EDI, EAX
46419 XCHG EDX, EAX
46420 OR ECX, -1
46421 XOR EAX, EAX
46422 CMP EAX, EDI
46423 JE @@exit0
46424 REPNE SCASW
46425 DEC EAX
46426 DEC EAX
46427 SUB EAX, ECX
46428 @@exit0:
46429 MOV EDI, EDX
46430 end;
46432 //[procedure WStrCopy]
46433 procedure WStrCopy( Dest, Src: PWideChar );
46435 PUSH EDI
46436 PUSH ESI
46437 MOV ESI,EAX
46438 MOV EDI,EDX
46439 OR ECX, -1
46440 XOR EAX, EAX
46441 REPNE SCASW
46442 NOT ECX
46443 MOV EDI,ESI
46444 MOV ESI,EDX
46445 REP MOVSW
46446 POP ESI
46447 POP EDI
46448 end;
46450 //[function WStrCmp]
46451 function WStrCmp( W1, W2: PWideChar ): Integer;
46453 PUSH ESI
46454 PUSH EDI
46455 XCHG ESI, EAX
46456 MOV EDI, EDX
46457 XOR EAX, EAX
46458 CWDE
46459 @@loop: LODSW
46460 MOV DX, [EDI]
46461 INC EDI
46462 INC EDI
46463 CMP EAX, EDX
46464 JNE @@exit
46465 TEST EAX, EAX
46466 JNZ @@loop
46467 @@exit: SUB EAX, EDX
46468 POP EDI
46469 POP ESI
46470 end;
46472 {$IFNDEF _D2}
46474 //[function NewWStrList]
46475 function NewWStrList: PWStrList;
46476 begin
46477 new( Result, Create );
46478 end;
46480 { TWStrList }
46482 //[function TWStrList.Add]
46483 function TWStrList.Add(const W: WideString): Integer;
46484 begin
46485 Result := Count;
46486 Insert( Result, W );
46487 end;
46489 //[procedure TWStrList.AddWStrings]
46490 procedure TWStrList.AddWStrings(WL: PWStrList);
46491 begin
46492 Text := Text + WL.Text;
46493 end;
46495 //[function TWStrList.AppendToFile]
46496 function TWStrList.AppendToFile(const Filename: String): Boolean;
46497 var Strm: PStream;
46498 begin
46499 Strm := NewReadWriteFileStream( Filename );
46500 Result := Strm.Handle <> INVALID_HANDLE_VALUE;
46501 if Result then
46502 begin
46503 Strm.Position := Strm.Size;
46504 SaveToStream( Strm );
46505 end;
46506 Strm.Free;
46507 end;
46509 //[procedure TWStrList.Assign]
46510 procedure TWStrList.Assign(WL: PWStrList);
46511 begin
46512 Text := WL.Text;
46513 end;
46515 //[procedure TWStrList.Clear]
46516 procedure TWStrList.Clear;
46517 var I: Integer;
46518 P: Pointer;
46519 begin
46520 for I := 0 to Count-1 do
46521 begin
46522 P := fList.Items[ I ];
46523 if P <> nil then
46524 if not( (P >= fText) and (P <= fText + fTextBufSz) ) then
46525 FreeMem( P );
46526 end;
46527 if fText <> nil then
46528 FreeMem( fText );
46529 fText := nil;
46530 fTextBufSz := 0;
46531 fList.Clear;
46532 end;
46534 //[procedure TWStrList.Delete]
46535 procedure TWStrList.Delete(Idx: Integer);
46536 var P: Pointer;
46537 begin
46538 P := fList.Items[ Idx ];
46539 if P <> nil then
46540 if not( (P >= fText) and (P <= fText + fTextBufSz) ) then
46541 FreeMem( P );
46542 fList.Delete( Idx );
46543 end;
46545 //[destructor TWStrList.Destroy]
46546 destructor TWStrList.Destroy;
46547 begin
46548 Clear;
46549 fList.Free;
46550 inherited;
46551 end;
46553 //[function TWStrList.GetCount]
46554 function TWStrList.GetCount: Integer;
46555 begin
46556 Result := fList.Count;
46557 end;
46559 //[function TWStrList.GetItems]
46560 function TWStrList.GetItems(Idx: Integer): WideString;
46561 begin
46562 Result := PWideChar( fList.Items[ Idx ] );
46563 end;
46565 //[function TWStrList.GetPtrs]
46566 function TWStrList.GetPtrs(Idx: Integer): PWideChar;
46567 begin
46568 Result := fList.Items[ Idx ];
46569 end;
46571 //[function TWStrList.GetText]
46572 function TWStrList.GetText: WideString;
46573 const
46574 EoL: array[ 0..5 ] of Char = ( #13, #0, #10, #0, #0, #0 );
46575 var L, I: Integer;
46576 P, Dest: Pointer;
46577 begin
46578 L := 0;
46579 for I := 0 to Count-1 do
46580 begin
46581 P := fList.Items[ I ];
46582 if P <> nil then
46583 L := L + WStrLen( P ) + 2
46584 else
46585 L := L + 2;
46586 end;
46587 SetLength( Result, L );
46588 Dest := PWideChar( Result );
46589 for I := 0 to Count-1 do
46590 begin
46591 P := fList.Items[ I ];
46592 if P <> nil then
46593 begin
46594 WStrCopy( Dest, P );
46595 Dest := Pointer( Integer( Dest ) + WStrLen( P ) * 2 );
46596 end;
46597 WStrCopy( Dest, Pointer( @ EoL[ 0 ] ) );
46598 Dest := Pointer( Integer( Dest ) + 4 );
46599 end;
46600 end;
46602 //[procedure TWStrList.Init]
46603 procedure TWStrList.Init;
46604 begin
46605 fList := NewList;
46606 end;
46608 //[procedure TWStrList.Insert]
46609 procedure TWStrList.Insert(Idx: Integer; const W: WideString);
46610 var P: Pointer;
46611 begin
46612 while Idx < Count-2 do
46613 fList.Add( nil );
46614 GetMem( P, (Length( W ) + 1) * 2 );
46615 fList.Insert( Idx, P );
46616 WStrCopy( P, PWideChar( W ) );
46617 end;
46619 //[function TWStrList.LoadFromFile]
46620 function TWStrList.LoadFromFile(const Filename: String): Boolean;
46621 begin
46622 Clear;
46623 Result := MergeFromFile( Filename );
46624 end;
46626 //[procedure TWStrList.LoadFromStream]
46627 procedure TWStrList.LoadFromStream(Strm: PStream);
46628 begin
46629 Clear;
46630 MergeFromStream( Strm );
46631 end;
46633 //[function TWStrList.MergeFromFile]
46634 function TWStrList.MergeFromFile(const Filename: String): Boolean;
46635 var Strm: PStream;
46636 begin
46637 Strm := NewReadFileStream( Filename );
46638 Result := Strm.Handle <> INVALID_HANDLE_VALUE;
46639 if Result then
46640 MergeFromStream( Strm );
46641 Strm.Free;
46642 end;
46644 //[procedure TWStrList.MergeFromStream]
46645 procedure TWStrList.MergeFromStream(Strm: PStream);
46646 var Buf: WideString;
46647 L: Integer;
46648 begin
46649 L := Strm.Size - Strm.Position;
46650 Assert( L mod 1 = 0, 'Wide strings streams must be of even length in bytes.' );
46651 if L = 0 then Exit;
46652 SetLength( Buf, L div 2 );
46653 Strm.Read( Buf[ 1 ], L );
46654 Text := Text + Buf;
46655 end;
46657 //[procedure TWStrList.Move]
46658 procedure TWStrList.Move(IdxOld, IdxNew: Integer);
46659 begin
46660 fList.MoveItem( IdxOld, IdxNew );
46661 end;
46663 //[function TWStrList.SaveToFile]
46664 function TWStrList.SaveToFile(const Filename: String): Boolean;
46665 var Strm: PStream;
46666 begin
46667 Strm := NewWriteFileStream( Filename );
46668 Result := Strm.Handle <> INVALID_HANDLE_VALUE;
46669 if Result then
46670 SaveToStream( Strm );
46671 Strm.Free;
46672 end;
46674 //[procedure TWStrList.SaveToStream]
46675 procedure TWStrList.SaveToStream(Strm: PStream);
46676 var Buf, Dest: PWideChar;
46677 I, L, Sz: Integer;
46678 P: Pointer;
46679 begin
46680 Sz := 0;
46681 for I := 0 to Count-1 do
46682 begin
46683 P := fList.Items[ I ];
46684 if P <> nil then
46685 Sz := Sz + WStrLen( P ) * 2 + 4
46686 else
46687 Sz := Sz + 4;
46688 end;
46689 GetMem( Buf, Sz );
46690 Dest := Buf;
46691 for I := 0 to Count-1 do
46692 begin
46693 P := fList.Items[ I ];
46694 if P <> nil then
46695 begin
46696 L := WStrLen( P );
46697 System.Move( P^, Dest^, L * 2 );
46698 Inc( Dest, L );
46699 end;
46700 Dest^ := #13;
46701 Inc( Dest );
46702 Dest^ := #10;
46703 Inc( Dest );
46704 end;
46705 Strm.Write( Buf^, Sz );
46706 FreeMem( Buf );
46707 end;
46709 //[procedure TWStrList.SetItems]
46710 procedure TWStrList.SetItems(Idx: Integer; const Value: WideString);
46711 var P: Pointer;
46712 begin
46713 while Idx > Count-1 do
46714 fList.Add( nil );
46715 if WStrLen( ItemPtrs[ Idx ] ) <= Length( Value ) then
46716 WStrCopy( ItemPtrs[ Idx ], PWideChar( Value ) )
46717 else
46718 begin
46719 P := fList.Items[ Idx ];
46720 if P <> nil then
46721 if not ((P >= fText) and (P <= fText + fTextBufSz)) then
46722 FreeMem( P );
46723 GetMem( P, (Length( Value ) + 1) * 2 );
46724 fList.Items[ Idx ] := P;
46725 WStrCopy( P, PWideChar( Value ) );
46726 end;
46727 end;
46729 //[procedure TWStrList.SetText]
46730 procedure TWStrList.SetText(const Value: WideString);
46731 var L, N: Integer;
46732 P: PWideChar;
46733 begin
46734 Clear;
46735 if Value = '' then Exit;
46736 L := (Length( Value ) + 1) * 2;
46737 GetMem( fText, L );
46738 System.Move( Value[ 1 ], fText^, L );
46739 fTextBufSz := Length( Value );
46740 N := 0;
46741 P := fText;
46742 while Word( P^ ) <> 0 do
46743 begin
46744 if (Word( P^ ) = 13) then
46745 begin
46746 Inc( N );
46747 PWord( P )^ := 0;
46748 if Word( P[ 1 ] ) = 10 then
46749 Inc( P );
46751 else
46752 if (Word( P^ ) = 10) and ((P = fText) or (Word( P[ -1 ] ) <> 0)) then
46753 begin
46754 Inc( N );
46755 PWord( P )^ := 0;
46756 end;
46757 Inc( P );
46758 end;
46759 fList.Capacity := N;
46760 P := fText;
46761 while P < fText + fTextBufSz do
46762 begin
46763 fList.Add( P );
46764 while Word( P^ ) <> 0 do Inc( P );
46765 Inc( P );
46766 if Word( P^ ) = 10 then Inc( P );
46767 end;
46768 end;
46770 //[function CompareWStrListItems]
46771 function CompareWStrListItems( const Sender: Pointer; const Idx1, Idx2: DWORD ): Integer;
46772 var WL: PWStrList;
46773 begin
46774 WL := Sender;
46775 Result := WStrCmp( WL.fList.Items[ Idx1 ], WL.fList.Items[ Idx2 ] );
46776 end;
46778 //[function CompareWStrListItems_UpperCase]
46779 function CompareWStrListItems_UpperCase( const Sender: Pointer; const Idx1, Idx2: DWORD ): Integer;
46780 var WL: PWStrList;
46781 L1, L2: Integer;
46782 begin
46783 WL := Sender;
46784 L1 := WStrLen( WL.fList.Items[ Idx1 ] );
46785 L2 := WStrLen( WL.fList.Items[ Idx2 ] );
46786 if Length( WL.fTmp1 ) < L1 then
46787 SetLength( WL.fTmp1, L1 + 1 );
46788 if Length( WL.fTmp2 ) < L2 then
46789 SetLength( WL.fTmp2, L2 + 1 );
46790 if L1 > 0 then
46791 Move( WL.fList.Items[ Idx1 ]^, WL.fTmp1[ 1 ], (L1 + 1) * 2 )
46792 else
46793 WL.fTmp1[ 1 ] := #0;
46794 if L2 > 0 then
46795 Move( WL.fList.Items[ Idx2 ]^, WL.fTmp2[ 1 ], (L2 + 1) * 2 )
46796 else
46797 WL.fTmp2[ 1 ] := #0;
46798 CharUpperBuffW( PWideChar( WL.fTmp1 ), L1 );
46799 CharUpperBuffW( PWideChar( WL.fTmp2 ), L2 );
46800 Result := WStrCmp( PWideChar( WL.fTmp1 ), PWideChar( WL.fTmp2 ) );
46801 end;
46803 //[procedure SwapWStrListItems]
46804 procedure SwapWStrListItems( const Sender: Pointer; const Idx1, Idx2: DWORD );
46805 var WL: PWStrList;
46806 begin
46807 WL := Sender;
46808 WL.Swap( Idx1, Idx2 );
46809 end;
46811 //[procedure TWStrList.Sort]
46812 procedure TWStrList.Sort( CaseSensitive: Boolean );
46813 begin
46814 if CaseSensitive then
46815 SortData( @ Self, Count, @CompareWStrListItems, @SwapWStrListItems )
46816 else
46817 begin
46818 SortData( @ Self, Count, @CompareWStrListItems_UpperCase, @SwapWStrListItems );
46819 fTmp1 := '';
46820 fTmp2 := '';
46821 end;
46822 end;
46824 //[procedure TWStrList.Swap]
46825 procedure TWStrList.Swap(Idx1, Idx2: Integer);
46826 begin
46827 fList.Swap( Idx1, Idx2 );
46828 end;
46830 //[function NewWStrListEx]
46831 function NewWStrListEx: PWStrListEx;
46832 begin
46833 new( Result, Create );
46834 end;
46836 { TWStrListEx }
46838 //[function TWStrListEx.AddObject]
46839 function TWStrListEx.AddObject(const S: WideString; Obj: DWORD): Integer;
46840 begin
46841 Result := Count;
46842 InsertObject( Count, S, Obj );
46843 end;
46845 //[procedure TWStrListEx.AddWStrings]
46846 procedure TWStrListEx.AddWStrings(WL: PWStrListEx);
46847 var I: Integer;
46848 begin
46849 I := Count;
46850 if WL.FObjects.Count > 0 then
46851 ProvideObjectsCapacity( Count );
46852 inherited AddWStrings( WL );
46853 if WL.FObjects.Count > 0 then
46854 begin
46855 ProvideObjectsCapacity( I + WL.FObjects.Count );
46856 System.Move( WL.FObjects.FItems[ 0 ],
46857 FObjects.FItems[ I ],
46858 Sizeof( Pointer ) * WL.FObjects.Count );
46859 end;
46860 end;
46862 //[procedure TWStrListEx.Assign]
46863 procedure TWStrListEx.Assign(WL: PWStrListEx);
46864 begin
46865 inherited Assign( WL );
46866 FObjects.Assign( WL.FObjects );
46867 end;
46869 //[procedure TWStrListEx.Clear]
46870 procedure TWStrListEx.Clear;
46871 begin
46872 inherited Clear;
46873 FObjects.Clear;
46874 end;
46876 //[procedure TWStrListEx.Delete]
46877 procedure TWStrListEx.Delete(Idx: Integer);
46878 begin
46879 inherited Delete( Idx );
46880 if FObjects.FCount >= Idx then
46881 FObjects.Delete( Idx );
46882 end;
46884 //[destructor TWStrListEx.Destroy]
46885 destructor TWStrListEx.Destroy;
46886 begin
46887 fObjects.Free;
46888 inherited;
46889 end;
46891 //[function TWStrListEx.GetObjects]
46892 function TWStrListEx.GetObjects(Idx: Integer): DWORD;
46893 begin
46894 Result := DWORD( fObjects.Items[ Idx ] );
46895 end;
46897 //[function TWStrListEx.IndexOfObj]
46898 function TWStrListEx.IndexOfObj(Obj: Pointer): Integer;
46899 begin
46900 Result := FObjects.IndexOf( Obj );
46901 end;
46903 //[procedure TWStrListEx.Init]
46904 procedure TWStrListEx.Init;
46905 begin
46906 inherited;
46907 fObjects := NewList;
46908 end;
46910 //[procedure TWStrListEx.InsertObject]
46911 procedure TWStrListEx.InsertObject(Before: Integer; const S: WideString;
46912 Obj: DWORD);
46913 begin
46914 Insert( Before, S );
46915 FObjects.Insert( Before, Pointer( Obj ) );
46916 end;
46918 //[procedure TWStrListEx.Move]
46919 procedure TWStrListEx.Move(IdxOld, IdxNew: Integer);
46920 begin
46921 fList.MoveItem( IdxOld, IdxNew );
46922 if FObjects.FCount >= Min( IdxOld, IdxNew ) then
46923 begin
46924 ProvideObjectsCapacity( Max( IdxOld, IdxNew ) + 1 );
46925 FObjects.MoveItem( IdxOld, IdxNew );
46926 end;
46927 end;
46929 //[procedure TWStrListEx.ProvideObjectsCapacity]
46930 procedure TWStrListEx.ProvideObjectsCapacity(NewCap: Integer);
46931 begin
46932 if fObjects.Capacity >= NewCap then Exit;
46933 fObjects.Capacity := NewCap;
46934 FillChar( FObjects.FItems[ FObjects.FCount ],
46935 (FObjects.Capacity - FObjects.Count) * Sizeof( Pointer ), 0 );
46936 FObjects.FCount := NewCap;
46937 end;
46939 //[procedure TWStrListEx.SetObjects]
46940 procedure TWStrListEx.SetObjects(Idx: Integer; const Value: DWORD);
46941 begin
46942 ProvideObjectsCapacity( Idx + 1 );
46943 fObjects.Items[ Idx ] := Pointer( Value );
46944 end;
46946 {$ENDIF}
46950 //////////////////////////////////////////////////////////////////////////
46953 // S O R T I N G
46956 //////////////////////////////////////////////////////////////////////////
46958 { -- qsort -- }
46960 //[PROCEDURE SortData]
46961 {$IFDEF ASM_VERSION} // translated to BASM by Kladov Vladimir
46962 procedure SortData( const Data: Pointer; const uNElem: Dword;
46963 const CompareFun: TCompareEvent;
46964 const SwapProc: TSwapEvent );
46966 CMP EDX, 2
46967 JL @@exit
46969 PUSH EAX // [EBP-4] = Data
46970 PUSH ECX // [EBP-8] = CompareFun
46971 PUSH EBX // EBX = pivotP
46972 XOR EBX, EBX
46973 INC EBX // EBX = 1 to pass to qSortHelp as PivotP
46974 MOV EAX, EDX // EAX = nElem
46975 CALL @@qSortHelp
46976 POP EBX
46977 POP ECX
46978 POP ECX
46979 @@exit:
46980 POP EBP
46981 RET 4
46983 @@qSortHelp:
46984 PUSH EBX // EBX (in) = PivotP
46985 PUSH ESI // ESI = leftP
46986 PUSH EDI // EDI = rightP
46988 @@TailRecursion:
46989 CMP EAX, 2
46990 JG @@2
46991 JNE @@exit_qSortHelp
46992 LEA ECX, [EBX+1]
46993 MOV EDX, EBX
46994 CALL @@Compare
46995 JLE @@exit_qSortHelp
46996 @@swp_exit:
46997 CALL @@Swap
46998 @@exit_qSortHelp:
46999 POP EDI
47000 POP ESI
47001 POP EBX
47004 // ESI = leftP
47005 // EDI = rightP
47006 @@2: LEA EDI, [EAX+EBX-1]
47007 MOV ESI, EAX
47008 SHR ESI, 1
47009 ADD ESI, EBX
47010 MOV ECX, ESI
47011 MOV EDX, EDI
47012 CALL @@CompareLeSwap
47013 MOV EDX, EBX
47014 CALL @@Compare
47016 JG @@4
47017 CALL @@Swap
47018 JMP @@5
47019 @@4: MOV ECX, EBX
47020 MOV EDX, EDI
47021 CALL @@CompareLeSwap
47022 @@5:
47023 CMP EAX, 3
47024 JNE @@6
47025 MOV EDX, EBX
47026 MOV ECX, ESI
47027 JMP @@swp_exit
47028 @@6: // classic Horae algorithm
47030 PUSH EAX // EAX = pivotEnd
47031 LEA EAX, [EBX+1]
47032 MOV ESI, EAX
47033 @@repeat:
47034 MOV EDX, ESI
47035 MOV ECX, EBX
47036 CALL @@Compare
47037 JG @@while2
47038 @@while1:
47039 JNE @@7
47040 MOV EDX, ESI
47041 MOV ECX, EAX
47042 CALL @@Swap
47043 INC EAX
47044 @@7:
47045 CMP ESI, EDI
47046 JGE @@qBreak
47047 INC ESI
47048 JMP @@repeat
47049 @@while2:
47050 CMP ESI, EDI
47051 JGE @@until
47052 MOV EDX, EBX
47053 MOV ECX, EDI
47054 CALL @@Compare
47055 JGE @@8
47056 DEC EDI
47057 JMP @@while2
47058 @@8:
47059 MOV EDX, ESI
47060 MOV ECX, EDI
47061 PUSHFD
47062 CALL @@Swap
47063 POPFD
47064 JE @@until
47065 INC ESI
47066 DEC EDI
47067 @@until:
47068 CMP ESI, EDI
47069 JL @@repeat
47070 @@qBreak:
47071 MOV EDX, ESI
47072 MOV ECX, EBX
47073 CALL @@Compare
47074 JG @@9
47075 INC ESI
47076 @@9:
47077 PUSH EBX // EBX = PivotTemp
47078 PUSH ESI // ESI = leftTemp
47079 DEC ESI
47080 @@while3:
47081 CMP EBX, EAX
47082 JGE @@while3_break
47083 CMP ESI, EAX
47084 JL @@while3_break
47085 MOV EDX, EBX
47086 MOV ECX, ESI
47087 CALL @@Swap
47088 INC EBX
47089 DEC ESI
47090 JMP @@while3
47091 @@while3_break:
47092 POP ESI
47093 POP EBX
47095 MOV EDX, EAX
47096 POP EAX // EAX = nElem
47097 PUSH EDI // EDI = lNum
47098 MOV EDI, ESI
47099 SUB EDI, EDX
47100 ADD EAX, EBX
47101 SUB EAX, ESI
47103 PUSH EBX
47104 PUSH EAX
47105 CMP EAX, EDI
47106 JGE @@10
47108 MOV EBX, ESI
47109 CALL @@qSortHelp
47110 POP EAX
47111 MOV EAX, EDI
47112 POP EBX
47113 JMP @@11
47115 @@10: MOV EAX, EDI
47116 CALL @@qSortHelp
47117 POP EAX
47118 POP EBX
47119 MOV EBX, ESI
47120 @@11:
47121 POP EDI
47122 JMP @@TailRecursion
47124 @@Compare:
47125 PUSH EAX
47126 PUSH EDX
47127 PUSH ECX
47128 MOV EAX, [EBP-4]
47129 DEC EDX
47130 DEC ECX
47131 CALL dword ptr [EBP-8]
47132 POP ECX
47133 POP EDX
47134 TEST EAX, EAX
47135 POP EAX
47138 @@CompareLeSwap:
47139 CALL @@Compare
47140 JG @@ret
47142 @@Swap: PUSH EAX
47143 PUSH EDX
47144 PUSH ECX
47145 MOV EAX, [EBP-4]
47146 DEC EDX
47147 DEC ECX
47148 CALL dword ptr [SwapProc]
47149 POP ECX
47150 POP EDX
47151 TEST EAX, EAX
47152 POP EAX
47153 @@ret:
47156 end;
47157 {$ELSE ASM_VERSION} //Pascal
47158 procedure SortData( const Data: Pointer; const uNElem: Dword;
47159 const CompareFun: TCompareEvent;
47160 const SwapProc: TSwapEvent );
47161 { uNElem - number of elements to sort }
47163 function Compare( const e1, e2 : DWord ) : Integer;
47164 begin
47165 Result := CompareFun( Data, e1 - 1, e2 - 1 );
47166 end;
47168 procedure Swap( const e1, e2 : DWord );
47169 begin
47170 SwapProc( Data, e1 - 1, e2 - 1 );
47171 end;
47173 procedure qSortHelp(pivotP: Dword; nElem: Dword);
47174 label
47175 TailRecursion,
47176 qBreak;
47178 leftP, rightP, pivotEnd, pivotTemp, leftTemp: Dword;
47179 lNum: Dword;
47180 retval: integer;
47181 begin
47182 TailRecursion:
47183 if (nElem <= 2) then
47184 begin
47185 if (nElem = 2) then
47186 begin
47187 rightP := pivotP +1;
47188 retval := Compare(pivotP,rightP);
47189 if (retval > 0) then Swap(pivotP,rightP);
47190 end;
47191 exit;
47192 end;
47193 rightP := (nElem -1) + pivotP;
47194 leftP := (nElem shr 1) + pivotP;
47195 { sort pivot, left, and right elements for "median of 3" }
47196 retval := Compare(leftP,rightP);
47197 if (retval > 0) then Swap(leftP, rightP);
47198 retval := Compare(leftP,pivotP);
47200 if (retval > 0) then
47201 Swap(leftP, pivotP)
47202 else
47203 begin
47204 retval := Compare(pivotP,rightP);
47205 if retval > 0 then Swap(pivotP, rightP);
47206 end;
47207 if (nElem = 3) then
47208 begin
47209 Swap(pivotP, leftP);
47210 exit;
47211 end;
47212 { now for the classic Horae algorithm }
47213 pivotEnd := pivotP + 1;
47214 leftP := pivotEnd;
47215 repeat
47217 retval := Compare(leftP, pivotP);
47218 while (retval <= 0) do
47219 begin
47221 if (retval = 0) then
47222 begin
47223 Swap(leftP, pivotEnd);
47224 Inc(pivotEnd);
47225 end;
47226 if (leftP < rightP) then
47227 Inc(leftP)
47228 else
47229 goto qBreak;
47230 retval := Compare(leftP, pivotP);
47231 end; {while}
47232 while (leftP < rightP) do
47233 begin
47234 retval := Compare(pivotP, rightP);
47235 if (retval < 0) then
47236 Dec(rightP)
47238 else
47239 begin
47240 Swap(leftP, rightP);
47241 if (retval <> 0) then
47242 begin
47243 Inc(leftP);
47244 Dec(rightP);
47245 end;
47246 break;
47247 end;
47248 end; {while}
47250 until (leftP >= rightP);
47251 qBreak:
47252 retval := Compare(leftP,pivotP);
47253 if (retval <= 0) then Inc(leftP);
47255 leftTemp := leftP -1;
47256 pivotTemp := pivotP;
47257 while ((pivotTemp < pivotEnd) and (leftTemp >= pivotEnd)) do
47258 begin
47259 Swap(pivotTemp, leftTemp);
47260 Inc(pivotTemp);
47261 Dec(leftTemp);
47262 end; {while}
47263 lNum := (leftP - pivotEnd);
47264 nElem := ((nElem + pivotP) -leftP);
47266 if (nElem < lNum) then
47267 begin
47268 qSortHelp(leftP, nElem);
47269 nElem := lNum;
47271 else
47272 begin
47273 qSortHelp(pivotP, lNum);
47274 pivotP := leftP;
47275 end;
47276 goto TailRecursion;
47277 end; {qSortHelp }
47279 begin
47280 if (uNElem < 2) then exit; { nothing to sort }
47281 qSortHelp(1, uNElem);
47282 end;
47283 {$ENDIF ASM_VERSION}
47284 //[END SortData]
47286 //[FUNCTION CompareIntegers]
47287 {$IFDEF ASM_VERSION}
47288 function CompareIntegers( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;
47290 MOV EDX, [EAX+EDX*4]
47291 SUB EDX, [EAX+ECX*4]
47292 XCHG EAX, EDX
47293 end;
47294 {$ELSE ASM_VERSION} //Pascal
47295 function CompareIntegers( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;
47296 var I1, I2 : Integer;
47297 begin
47298 I1 := PInteger( DWORD( Sender ) + e1 * Sizeof( Integer ) )^;
47299 I2 := PInteger( DWORD( Sender ) + e2 * Sizeof( Integer ) )^;
47300 Result := 0;
47301 if I1 < I2 then Result := -1
47302 else
47303 if I1 > I2 then Result := 1;
47304 end;
47305 {$ENDIF ASM_VERSION}
47306 //[END CompareIntegers]
47308 //[FUNCTION CompareDwords]
47309 {$IFDEF ASM_VERSION}
47310 function CompareDwords( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;
47312 MOV EDX, [EAX+EDX*4]
47313 SUB EDX, [EAX+ECX*4]
47314 XCHG EAX, EDX
47315 JNB @@1
47316 SBB EAX, EAX
47317 @@1:
47318 end;
47319 {$ELSE ASM_VERSION} //Pascal
47320 function CompareDwords( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;
47321 var I1, I2 : DWord;
47322 begin
47323 I1 := PDWORD( DWORD( Sender ) + e1 * Sizeof( Integer ) )^;
47324 I2 := PDWORD( DWORD( Sender ) + e2 * Sizeof( Integer ) )^;
47325 Result := 0;
47326 if I1 < I2 then Result := -1
47327 else
47328 if I1 > I2 then Result := 1;
47329 end;
47330 {$ENDIF ASM_VERSION}
47331 //[END CompareDwords]
47333 //[PROCEDURE SwapIntegers]
47334 {$IFDEF ASM_VERSION}
47335 procedure SwapIntegers( const Sender : Pointer; const e1, e2 : DWORD );
47337 LEA EDX, [EAX+EDX*4]
47338 LEA ECX, [EAX+ECX*4]
47339 MOV EAX, [EDX]
47340 XCHG EAX, [ECX]
47341 MOV [EDX], EAX
47342 end;
47343 {$ELSE ASM_VERSION} //Pascal
47344 procedure SwapIntegers( const Sender : Pointer; const e1, e2 : DWORD );
47345 var Tmp : Integer;
47346 begin
47347 Tmp := PInteger( DWORD( Sender ) + e1 * SizeOf( Integer ) )^;
47348 PInteger( DWORD( Sender ) + e1 * Sizeof( Integer ) )^ :=
47349 PInteger( DWORD( Sender ) + e2 * Sizeof( Integer ) )^;
47350 PInteger( DWORD( Sender ) + e2 * Sizeof( Integer ) )^ := Tmp;
47351 end;
47352 {$ENDIF ASM_VERSION}
47353 //[END SwapIntegers]
47355 //[procedure SortIntegerArray]
47356 procedure SortIntegerArray( var A : array of Integer );
47357 begin
47358 SortData( @A[ 0 ], High( A ) - Low( A ) + 1, @CompareIntegers, @SwapIntegers );
47359 end;
47361 //[procedure SortDwordArray]
47362 procedure SortDwordArray( var A : array of DWORD );
47363 begin
47364 SortData( @A[ 0 ], High( A ) - Low( A ) + 1, @CompareDwords, @SwapIntegers );
47365 end;
47368 { -- status bar implementation -- }
47370 //[FUNCTION _NewStatusbar]
47371 {$IFDEF ASM_VERSION}
47372 function _NewStatusbar( AParent: PControl ): PControl;
47373 const STAT_CLS_NAM: PChar = STATUSCLASSNAME;
47375 PUSH 0
47376 PUSH 0
47377 //PUSH EAX
47378 //CALL TControl.GetCanResize
47379 CMP [EAX].TControl.fSizeGrip, 0
47380 MOV ECX, WS_CHILD or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or 3 or WS_VISIBLE
47381 //MOV CH, AL // SBARS_SIZEGRIP = $0100
47382 JZ @@1
47383 //SETNZ CH
47384 INC CH
47385 AND CL, not 3
47386 @@1:
47387 //POP EAX
47388 MOV EDX, [STAT_CLS_NAM]
47389 CALL _NewCommonControl
47390 PUSH EBX
47391 XCHG EBX, EAX
47392 PUSH EDI
47393 LEA EDI, [EBX].TControl.fBoundsRect
47394 XOR EAX, EAX
47395 STOSD
47396 STOSD
47397 STOSD
47398 STOSD
47399 MOV [EBX].TControl.fAlign, caBottom
47400 INC [EBX].TControl.fNotUseAlign
47401 POP EDI
47402 MOV EAX, EBX
47403 CALL InitCommonControlSizeNotify
47404 XCHG EAX, EBX
47405 POP EBX
47406 end;
47407 {$ELSE ASM_VERSION} //Pascal
47408 function _NewStatusbar( AParent: PControl ): PControl;
47409 var Style: DWORD;
47410 //R: TRect;
47411 begin
47412 Style := WS_CHILD or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or 3 or WS_VISIBLE;
47413 {if AParent.CanResize then
47414 Style := Style or SBARS_SIZEGRIP;}
47415 if AParent.fSizeGrip then
47416 Style := (Style or SBARS_SIZEGRIP) and not 3;
47417 Result := _NewCommonControl( AParent, STATUSCLASSNAME,
47418 Style, FALSE, nil );
47420 with Result.fBoundsRect do
47421 begin
47422 Left := 0;
47423 Right := 0;
47424 Top := 0;
47425 Bottom := 0;
47426 end;
47427 Result.fAlign := caBottom;
47428 Result.fNotUseAlign := True;
47429 {$IFDEF TEST_VERSION}
47430 Result.fTag := DWORD( PChar( 'Status bar' ) );
47431 {$ENDIF}
47432 InitCommonControlSizeNotify( Result );
47433 //R := AParent.ClientRect;
47434 //AParent.Perform( WM_SIZING, WMSZ_TOPLEFT, Integer( @ R ) );
47435 //Result.AttachProc( WndProcEraseBkgnd );
47436 end;
47437 {$ENDIF ASM_VERSION}
47438 //[END _NewStatusbar]
47440 {$IFDEF ASM_VERSION}
47441 //[procedure TControl.SetStatusText]
47442 procedure TControl.SetStatusText(Index: Integer; Value: PChar);
47444 PUSHAD
47445 MOV EBX, EDX // EBX = Index
47446 MOV ESI, EAX // ESI = @Self
47448 PUSH Value // prepare value for call at the end of procedure
47449 PUSH EBX // prepare Index for call at the end of procedure
47451 MOV ECX, [ESI].fStatusCtl
47452 INC ECX
47453 LOOP @@status_created
47455 CALL GetClientHeight
47456 PUSH EAX // ch = old client height
47458 MOV EAX, ESI
47459 CALL _NewStatusBar
47460 MOV [ESI].fStatusCtl, EAX
47461 PUSH EAX //-----------v
47463 CALL TControl.GetWindowHandle
47464 MOV [ESI].fStatusWnd, EAX
47465 XCHG EDI, EAX
47466 POP EAX //-----------^
47468 XOR EDX, EDX
47469 PUSH EDX
47470 INC DH
47471 DEC EDX
47472 CMP EBX, EDX
47473 SETZ DL
47474 NEG EDX
47476 @@1: PUSH EDX
47477 PUSH SB_SIMPLE
47479 PUSH EAX
47480 CALL TControl.Perform
47482 ADD ESP, -16
47483 PUSH ESP
47484 PUSH [ESI].fStatusWnd
47485 CALL GetWindowRect
47486 POP EAX
47487 POP EDX
47488 POP EAX
47489 POP EAX
47490 SUB EAX, EDX
47491 MOV [ESI].fClientBottom, EAX
47493 POP EDX // ch
47495 PUSH 0
47496 PUSH 0
47497 PUSH WM_SIZE
47498 PUSH EDI
47500 MOV EAX, ESI
47501 CALL TControl.SetClientHeight
47503 CALL SendMessage
47505 @@status_created:
47506 CMP EBX, 255
47507 JGE @@not_simple
47509 PUSH 0
47510 PUSH 0
47511 PUSH SB_GETPARTS
47512 PUSH [ESI].fStatusWnd
47513 CALL SendMessage
47515 CMP EAX, EBX
47516 JG @@reset_simple
47518 MOV EAX, ESI
47519 CALL GetWidth
47521 MOV ECX, EBX
47522 INC ECX
47523 IDIV ECX
47524 MOV EDX, EAX
47526 ADD ESP, -1024
47527 MOV ECX, EBX
47528 MOV EDI, ESP
47529 JECXZ @@2
47531 @@store_loo:
47532 STOSD
47533 ADD EAX, EDX
47534 LOOP @@store_loo
47535 @@2:
47536 OR dword ptr [ESP+EBX*4], -1
47537 PUSH ESP
47538 INC EBX
47539 PUSH EBX
47540 PUSH SB_SETPARTS
47541 PUSH [ESI].fStatusWnd
47542 CALL SendMessage
47543 ADD ESP, 1024
47545 @@reset_simple:
47546 PUSH 0
47547 PUSH 0
47548 PUSH SB_SIMPLE
47549 PUSH [ESI].fStatusWnd
47550 CALL SendMessage
47552 @@not_simple:
47553 PUSH SB_SETTEXT
47554 PUSH [ESI].fStatusWnd
47555 CALL SendMessage
47556 POPAD
47557 end;
47558 {$ELSE ASM_VERSION} //Pascal
47559 procedure TControl.SetStatusText(Index: Integer; Value: PChar);
47560 var ch: Integer;
47561 R : TRect;
47562 N, I, L, W : Integer;
47563 WidthsBuf: array[ 0..254 ] of Integer;
47564 begin
47565 if fStatusCtl = nil then
47566 begin
47567 ch := GetClientHeight;
47568 fStatusCtl := _NewStatusBar( @Self );
47569 fStatusWnd := fStatusCtl.GetWindowHandle;
47570 fStatusCtl.Perform( SB_SIMPLE, Integer( LongBool( Index = 255 ) ), 0 );
47571 GetWindowRect( fStatusWnd, R );
47572 fClientBottom := R.Bottom - R.Top;
47573 SetClientHeight( ch );
47574 SendMessage( fStatusWnd, WM_SIZE, 0, 0 );
47575 end;
47576 if Index < 255 then
47577 begin
47578 N := SendMessage( fStatusWnd, SB_GETPARTS, 0, 0 );
47579 if N <= Index then
47580 begin
47581 W := Width;
47582 L := W div (Index + 1);
47583 W := L;
47584 for I := 0 to Index - 1 do
47585 begin
47586 WidthsBuf[ I ] := W;
47587 Inc( W, L );
47588 end;
47589 WidthsBuf[ Index ] := -1;
47590 SendMessage( fStatusWnd, SB_SETPARTS, Index + 1, Integer( @WidthsBuf[ 0 ] ) );
47591 end;
47592 SendMessage( fStatusWnd, SB_SIMPLE, 0, 0 );
47593 end;
47594 SendMessage( fStatusWnd, SB_SETTEXT, Index, Integer( Value ) );
47595 end;
47596 {$ENDIF ASM_VERSION}
47598 {$IFDEF ASM_VERSION}
47599 //[function TControl.GetStatusText]
47600 function TControl.GetStatusText( Index: Integer ): PChar;
47602 MOV ECX, [EAX].fStatusWnd
47603 JECXZ @@exit
47605 PUSH EBX
47606 PUSH ESI
47607 XCHG ESI, EAX // ESI = @Self
47608 MOV EBX, EDX // EBX = Index
47610 XOR EAX, EAX
47611 XCHG EAX, [ESI].fStatusTxt
47612 TEST EAX, EAX
47613 JZ @@1
47614 CALL System.@FreeMem
47615 @@1:
47616 XOR EAX, EAX
47618 MOV DL, WM_GETTEXTLENGTH
47619 PUSH WM_GETTEXT
47620 CMP EBX, 255
47621 JZ @@2
47622 POP EAX
47623 MOV EAX, EBX
47624 MOV DX, SB_GETTEXTLENGTH
47625 PUSH SB_GETTEXT
47626 @@2:
47627 MOV EBX, EAX
47629 PUSH 0
47630 PUSH EAX
47631 PUSH EDX
47632 PUSH [ESI].fStatusWnd
47633 CALL SendMessage
47634 TEST AX, AX
47635 JZ @@get_rslt
47637 PUSH EAX
47638 INC EAX
47639 CALL System.@GetMem
47640 POP EDX
47641 MOV [ESI].fStatusTxt, EAX
47642 MOV byte ptr [EAX+EDX], 0
47644 POP EDX // Msg
47645 PUSH EAX
47646 PUSH EBX
47647 PUSH EDX
47648 PUSH [ESI].fStatusWnd
47649 CALL SendMessage
47650 PUSH EDX
47651 @@get_rslt:
47652 POP EDX
47653 MOV ECX, [ESI].fStatusTxt
47654 POP ESI
47655 POP EBX
47657 @@exit: XCHG EAX, ECX
47658 end;
47659 {$ELSE ASM_VERSION} //Pascal
47660 function TControl.GetStatusText( Index: Integer ): PChar;
47661 var L, I: Integer;
47662 Msg: DWORD;
47663 begin
47664 Result := nil;
47665 if fStatusWnd = 0 then Exit;
47666 if fStatusTxt <> nil then
47667 FreeMem( fStatusTxt );
47668 fStatusTxt := nil;
47669 Msg := SB_GETTEXTLENGTH;
47670 I := Index;
47671 if Index = 255 then
47672 begin
47673 Msg := WM_GETTEXTLENGTH;
47674 I := 0;
47675 end;
47676 L := SendMessage( fStatusWnd, Msg, I, 0 ) and $FFFF;
47677 if L > 0 then
47678 begin
47679 GetMem( fStatusTxt, L + 1 );
47680 fStatusTxt[ L ] := #0;
47681 Msg := SB_GETTEXT;
47682 if Index = 255 then
47683 Msg := WM_GETTEXT;
47684 SendMessage( fStatusWnd, Msg, I, Integer( fStatusTxt ) );
47685 end;
47686 Result := fStatusTxt;
47687 end;
47688 {$ENDIF ASM_VERSION}
47690 {$IFDEF ASM_VERSION}
47691 //[procedure TControl.RemoveStatus]
47692 procedure TControl.RemoveStatus;
47694 MOV ECX, [EAX].fStatusCtl
47695 JECXZ @@exit
47696 PUSH EBX
47697 MOV EBX, EAX
47698 CALL GetClientHeight
47699 PUSH EAX
47701 MOV [EBX].fStatusWnd, EDX
47702 XCHG EAX, EDX
47703 XCHG [EBX].fStatusCtl, EAX
47704 CALL TControl.Free
47705 POP EAX
47707 MOV [EBX].fClientBottom, EDX
47708 XCHG EDX, EAX
47709 XCHG EAX, EBX
47710 POP EBX
47711 CALL SetClientHeight
47712 @@exit:
47713 end;
47714 {$ELSE ASM_VERSION} //Pascal
47715 procedure TControl.RemoveStatus;
47716 var ch: Integer;
47717 begin
47718 if fStatusCtl = nil then Exit;
47719 ch := ClientHeight;
47720 fStatusWnd := 0;
47721 fStatusCtl.Free;
47722 fStatusCtl := nil;
47723 fClientBottom := 0;
47724 ClientHeight := ch;
47725 end;
47726 {$ENDIF ASM_VERSION}
47728 {$IFDEF ASM_VERSION}
47729 //[function TControl.StatusPanelCount]
47730 function TControl.StatusPanelCount: Integer;
47732 MOV EAX, [EAX].fStatusWnd
47733 TEST EAX, EAX
47734 JZ @@exit
47735 PUSH 0
47736 PUSH 0
47737 PUSH SB_GETPARTS
47738 PUSH EAX
47739 CALL SendMessage
47740 @@exit:
47741 end;
47742 {$ELSE ASM_VERSION} //Pascal
47743 function TControl.StatusPanelCount: Integer;
47744 begin
47745 Result := 0;
47746 if fStatusWnd = 0 then Exit;
47747 Result := SendMessage( fStatusWnd, SB_GETPARTS, 0, 0 );
47748 end;
47749 {$ENDIF ASM_VERSION}
47751 {$IFDEF ASM_VERSION}
47752 //[function TControl.GetStatusPanelX]
47753 function TControl.GetStatusPanelX(Idx: Integer): Integer;
47755 MOV ECX, [EAX].fStatusWnd
47756 JECXZ @@exit
47757 PUSH EBX
47758 MOV EBX, EDX
47759 ADD ESP, -1024
47760 PUSH ESP
47761 XOR EDX, EDX
47762 DEC DL
47763 PUSH EDX
47764 MOV DX, SB_GETPARTS
47765 PUSH EDX
47766 PUSH ECX
47767 CALL SendMessage
47768 CMP EAX, EBX
47769 MOV ECX, [ESP+EBX*4]
47770 JG @@1
47771 XOR ECX, ECX
47772 @@1: ADD ESP, 1024
47773 POP EBX
47774 @@exit:
47775 XCHG EAX, ECX
47776 end;
47777 {$ELSE ASM_VERSION} //Pascal
47778 function TControl.GetStatusPanelX(Idx: Integer): Integer;
47779 var Buf: array[0..254] of Integer;
47780 N : Integer;
47781 begin
47782 Result := 0;
47783 if fStatusWnd = 0 then Exit;
47784 N := SendMessage( fStatusWnd, SB_GETPARTS, 255, Integer( @Buf[ 0 ] ) );
47785 if N <= Idx then Exit;
47786 Result := Buf[ Idx ];
47787 end;
47788 {$ENDIF ASM_VERSION}
47790 {$IFDEF ASM_VERSION}
47791 //[procedure TControl.SetStatusPanelX]
47792 procedure TControl.SetStatusPanelX(Idx: Integer; const Value: Integer);
47794 ADD ESP, -1024
47795 MOV EAX, [EAX].fStatusWnd
47796 TEST EAX, EAX
47797 JZ @@exit
47799 PUSH ESP
47800 PUSH EDX
47801 PUSH SB_SETPARTS
47802 PUSH EAX
47804 PUSH EDX
47805 PUSH ECX
47807 LEA EDX, [ESP+24]
47808 PUSH EDX
47809 PUSH 255
47810 PUSH SB_GETPARTS
47811 PUSH EAX
47812 CALL SendMessage
47814 POP ECX
47815 POP EDX
47816 CMP EAX, EDX
47817 JG @@1
47818 ADD ESP, 16
47819 JMP @@exit
47821 @@1: MOV [ESP+8], EAX
47822 MOV [ESP+16+EDX*4], ECX
47823 CALL SendMessage
47825 @@exit: ADD ESP, 1024
47826 end;
47827 {$ELSE ASM_VERSION} //Pascal
47828 procedure TControl.SetStatusPanelX(Idx: Integer; const Value: Integer);
47829 var Buf: array[0..254] of Integer;
47830 N : Integer;
47831 begin
47832 if fStatusWnd = 0 then Exit;
47833 N := SendMessage( fStatusWnd, SB_GETPARTS, 255, Integer( @Buf[ 0 ] ) );
47834 if N <= Idx then Exit;
47835 Buf[ Idx ] := Value;
47836 SendMessage( fStatusWnd, SB_SETPARTS, N, Integer( @Buf[ 0 ] ) );
47837 end;
47838 {$ENDIF ASM_VERSION}
47840 //[procedure TControl.SetColor1]
47841 procedure TControl.SetColor1(const Value: TColor);
47842 begin
47843 fColor1 := Value;
47844 Invalidate;
47845 end;
47847 //[procedure TControl.SetColor2]
47848 procedure TControl.SetColor2(const Value: TColor);
47849 begin
47850 fColor2 := Value;
47851 Invalidate;
47852 end;
47854 //[procedure TControl.SetGradientLayout]
47855 procedure TControl.SetGradientLayout(const Value: TGradientLayout);
47856 begin
47857 FGradientLayout := Value;
47858 Invalidate;
47859 end;
47861 //[procedure TControl.SetGradientStyle]
47862 procedure TControl.SetGradientStyle(const Value: TGradientStyle);
47863 begin
47864 FGradientStyle := Value;
47865 Invalidate;
47866 end;
47879 { -- Image List -- }
47882 {$IFDEF USE_CONSTRUCTORS}
47883 //[function NewImageList]
47884 function NewImageList( AOwner: PControl ): PImageList;
47885 begin
47886 new( Result, CreateImageList( AOwner ) );
47887 end;
47888 //[END NewImageList]
47889 {$ELSE not_USE_CONSTRUCTORS}
47890 //[function NewImageList]
47891 function NewImageList( AOwner: PControl ): PImageList;
47892 begin
47893 {*************} DoInitCommonControls( ICC_WIN95_CLASSES );
47895 New( Result, Create );
47897 {++}(*Result := TImageList.Create;*){--}
47898 Result.FAllocBy := 1;
47899 Result.FMasked := True;
47900 if AOwner = nil then exit;
47902 Result.FControl := AOwner;
47903 Result.fNext := PImageList( AOwner.fImageList );
47904 if AOwner.fImageList <> nil then
47905 PImageList( AOwner.fImageList ).fPrev := Result;
47906 Result.fBkColor := clNone;
47907 //ImageList_SetBkColor( Result.FHandle, CLR_NONE );
47908 AOwner.fImageList := Result;
47909 Result.FImgWidth := 32;
47910 Result.FImgHeight := 32;
47911 Result.FColors := ilcDefault;
47912 end;
47913 {$ENDIF}
47915 //[API ImageList_XXX]
47916 function ImageList_Create; stdcall; external cctrl name 'ImageList_Create';
47917 function ImageList_Destroy; external cctrl name 'ImageList_Destroy';
47918 function ImageList_GetImageCount; external cctrl name 'ImageList_GetImageCount';
47919 function ImageList_SetImageCount; external cctrl name 'ImageList_SetImageCount';
47920 function ImageList_Add; external cctrl name 'ImageList_Add';
47921 function ImageList_ReplaceIcon; external cctrl name 'ImageList_ReplaceIcon';
47922 function ImageList_SetBkColor; external cctrl name 'ImageList_SetBkColor';
47923 function ImageList_GetBkColor; external cctrl name 'ImageList_GetBkColor';
47924 function ImageList_SetOverlayImage; external cctrl name 'ImageList_SetOverlayImage';
47925 function ImageList_Draw; external cctrl name 'ImageList_Draw';
47926 function ImageList_Replace; external cctrl name 'ImageList_Replace';
47927 function ImageList_AddMasked; external cctrl name 'ImageList_AddMasked';
47928 function ImageList_DrawEx; external cctrl name 'ImageList_DrawEx';
47929 function ImageList_Remove; external cctrl name 'ImageList_Remove';
47930 function ImageList_GetIcon; external cctrl name 'ImageList_GetIcon';
47931 function ImageList_LoadImageA; external cctrl name 'ImageList_LoadImageA';
47932 function ImageList_LoadImageW; external cctrl name 'ImageList_LoadImageW';
47933 function ImageList_LoadImage; external cctrl name 'ImageList_LoadImageA';
47934 function ImageList_BeginDrag; external cctrl name 'ImageList_BeginDrag';
47935 function ImageList_EndDrag; external cctrl name 'ImageList_EndDrag';
47936 function ImageList_DragEnter; external cctrl name 'ImageList_DragEnter';
47937 function ImageList_DragLeave; external cctrl name 'ImageList_DragLeave';
47938 function ImageList_DragMove; external cctrl name 'ImageList_DragMove';
47939 function ImageList_SetDragCursorImage; external cctrl name 'ImageList_SetDragCursorImage';
47940 function ImageList_DragShowNolock; external cctrl name 'ImageList_DragShowNolock';
47941 function ImageList_GetDragImage; external cctrl name 'ImageList_GetDragImage';
47942 //function ImageList_Read; external cctrl name 'ImageList_Read';
47943 //function ImageList_Write; external cctrl name 'ImageList_Write';
47944 function ImageList_GetIconSize; external cctrl name 'ImageList_GetIconSize';
47945 function ImageList_SetIconSize; external cctrl name 'ImageList_SetIconSize';
47946 function ImageList_GetImageInfo; external cctrl name 'ImageList_GetImageInfo';
47947 function ImageList_Merge; external cctrl name 'ImageList_Merge';
47949 //[function ImageList_AddIcon]
47950 function ImageList_AddIcon(ImageList: HImageList; Icon: HIcon): Integer;
47951 begin
47952 Result := ImageList_ReplaceIcon(ImageList, -1, Icon);
47953 end;
47955 //[function Index2OverlayMask]
47956 function Index2OverlayMask(Index: Integer): Integer;
47957 begin
47958 Result := Index shl 8;
47959 end;
47961 { macros }
47962 //[procedure ImageList_RemoveAll]
47963 procedure ImageList_RemoveAll(ImageList: HImageList); stdcall;
47964 begin
47965 ImageList_Remove(ImageList, -1);
47966 end;
47968 //[function ImageList_ExtractIcon]
47969 function ImageList_ExtractIcon(Instance: THandle; ImageList: HImageList;
47970 Image: Integer): HIcon; stdcall;
47971 begin
47972 Result := ImageList_GetIcon(ImageList, Image, 0);
47973 end;
47975 //[function ImageList_LoadBitmap]
47976 function ImageList_LoadBitmap(Instance: THandle; Bmp: PChar;
47977 CX, Grow: Integer; Mask: TColorRef): HImageList; stdcall;
47978 begin
47979 Result := ImageList_LoadImage(Instance, Bmp, CX, Grow, Mask,
47980 IMAGE_BITMAP, 0);
47981 end;
47983 //[procedure FreeBmp]
47984 procedure FreeBmp( Bmp: HBitmap );
47985 begin
47986 DeleteObject( Bmp );
47987 end;
47989 //[function LoadBmp]
47990 function LoadBmp( Instance: Integer; Rsrc: PChar; MasterObj: PObj ): HBitmap;
47991 begin
47992 Result := LoadBitmap( Instance, Rsrc );
47993 MasterObj.Add2AutoFreeEx( TObjectMethod( MakeMethod( Pointer( Result ), @ FreeBmp ) ) );
47994 end;
47996 { TImageList }
47999 //[function TImageList.Add]
48000 function TImageList.Add(Bmp, Msk: HBitmap): Integer;
48001 begin
48002 Result := -1;
48003 if not HandleNeeded then Exit;
48004 Result := ImageList_Add( FHandle, Bmp, Msk );
48005 end;
48008 //[function TImageList.AddIcon]
48009 function TImageList.AddIcon(Ico: HIcon): Integer;
48010 {var Bmp : HBitmap;
48011 DC : HDC;}
48012 begin
48013 Result := -1;
48014 if ImgWidth = 0 then
48015 ImgWidth := 32;
48016 if ImgHeight = 0 then
48017 ImgHeight := 32;
48018 if not HandleNeeded then Exit;
48020 {DC := GetDC( 0 );
48021 Bmp := CreateCompatibleBitmap( DC, ImgWidth, ImgHeight );
48022 Result := AddMasked( Bmp, 0 );
48023 DeleteObject( Bmp );
48024 ReleaseDC( 0, DC );
48025 if Result >= 0 then
48026 ReplaceIcon( Result, Ico );}
48027 Result := ImageList_AddIcon( fHandle, Ico );
48028 end;
48031 //[function TImageList.AddMasked]
48032 function TImageList.AddMasked(Bmp: HBitmap; Color: TColor): Integer;
48033 begin
48034 Result := -1;
48035 if not HandleNeeded then Exit;
48036 Result := ImageList_AddMasked( FHandle, Bmp, Color2RGB( Color ) );
48037 end;
48040 //[procedure TImageList.Clear]
48041 procedure TImageList.Clear;
48042 begin
48043 Handle := 0;
48044 end;
48047 //[procedure TImageList.Delete]
48048 procedure TImageList.Delete(Idx: Integer);
48049 begin
48050 if FHandle = 0 then Exit;
48051 ImageList_Remove( FHandle, Idx );
48052 end;
48054 {$IFDEF ASM_VERSION}
48055 //[destructor TImageList.Destroy]
48056 destructor TImageList.Destroy;
48058 PUSH EAX
48059 XOR EDX, EDX
48060 CALL SetHandle
48061 POP EAX
48062 MOV EDX, [EAX].fNext
48063 MOV ECX, [EAX].fPrev
48064 TEST EDX, EDX
48065 JZ @@nonext
48066 MOV [EDX].fPrev, ECX
48067 @@nonext:
48068 JECXZ @@noprev
48069 MOV [ECX].fNext, EDX
48070 @@noprev:
48071 MOV ECX, [EAX].fControl
48072 JECXZ @@fin
48073 CMP [ECX].TControl.fImageList, EAX
48074 JNZ @@fin
48075 MOV [ECX].TControl.fImageList, EDX
48076 @@fin: CALL TObj.Destroy
48077 end;
48078 {$ELSE ASM_VERSION} //Pascal
48079 destructor TImageList.Destroy;
48080 begin
48081 Clear;
48082 if fNext <> nil then
48083 fNext.fPrev := fPrev;
48084 if fPrev <> nil then
48085 fPrev.fNext := fNext;
48086 if fControl <> nil then
48087 if PControl( fControl ).fImageList = @Self then
48088 PControl( fControl ).fImageList := fNext;
48089 inherited;
48090 end;
48091 {$ENDIF ASM_VERSION}
48094 //[procedure TImageList.Draw]
48095 procedure TImageList.Draw(Idx: Integer; DC: HDC; X, Y: Integer);
48096 begin
48097 if FHandle = 0 then Exit;
48098 ImageList_Draw( FHandle, Idx, DC, X, Y, GetDrawStyle );
48099 end;
48101 //[function TImageList.ExtractIcon]
48102 function TImageList.ExtractIcon(Idx: Integer): HIcon;
48103 begin
48104 Result := ImageList_ExtractIcon( 0, FHandle, Idx );
48105 end;
48107 //[function TImageList.ExtractIconEx]
48108 function TImageList.ExtractIconEx(Idx: Integer): HIcon;
48109 begin
48110 Result := ImageList_GetIcon( FHandle, Idx, GetDrawStyle );
48111 end;
48114 //[function TImageList.GetBitmap]
48115 function TImageList.GetBitmap: HBitmap;
48116 var II : TImageInfo;
48117 begin
48118 Result := 0;
48119 if FHandle = 0 then Exit;
48120 if ImageList_GetImageInfo( FHandle, 0, II ) then
48121 Result := II.hbmImage;
48122 end;
48125 //[function TImageList.GetBkColor]
48126 function TImageList.GetBkColor: TColor;
48127 begin
48128 Result := fBkColor;
48129 if FHandle = 0 then Exit;
48130 Result := ImageList_GetBkColor( FHandle );
48131 end;
48134 //[function TImageList.GetCount]
48135 function TImageList.GetCount: Integer;
48136 begin
48137 Result := 0;
48138 if FHandle <> 0 then
48139 Result := ImageList_GetImageCount( FHandle );
48140 end;
48143 //[function TImageList.GetDrawStyle]
48144 function TImageList.GetDrawStyle: DWord;
48145 begin
48146 Result := 0;
48147 if dsBlend25 in DrawingStyle then
48148 Result := Result or ILD_BLEND25;
48149 if dsBlend50 in DrawingStyle then
48150 Result := Result or ILD_BLEND50;
48151 if dsTransparent in DrawingStyle then
48152 Result := Result or ILD_TRANSPARENT
48153 else
48154 if dsMask in DrawingStyle then
48155 Result := Result or ILD_MASK
48156 {else
48157 Result := Result or ILD_NORMAL}; // ILD_NORMAL = 0
48158 end;
48160 {$IFDEF ASM_VERSION}
48161 //[function TImageList.GetHandle]
48162 function TImageList.GetHandle: THandle;
48164 PUSH EAX
48165 CALL HandleNeeded
48166 POP EAX
48167 MOV EAX, [EAX].FHandle
48168 end;
48169 {$ELSE ASM_VERSION} //Pascal
48170 function TImageList.GetHandle: THandle;
48171 begin
48172 HandleNeeded;
48173 Result := FHandle;
48174 end;
48175 {$ENDIF ASM_VERSION}
48178 //[function TImageList.GetMask]
48179 function TImageList.GetMask: HBitmap;
48180 var II : TImageInfo;
48181 begin
48182 Result := 0;
48183 if FHandle = 0 then Exit;
48184 if ImageList_GetImageInfo( FHandle, 0, II ) then
48185 Result := II.hbmMask;
48186 end;
48188 {$IFDEF ASM_noVERSION}
48189 //[function TImageList.HandleNeeded]
48190 function TImageList.HandleNeeded: Boolean;
48191 const ColorFlags : array[ TImageListColors ] of Byte = ( ILC_COLOR,
48192 ILC_COLOR4, ILC_COLOR8, ILC_COLOR16, ILC_COLOR24,
48193 ILC_COLOR32, ILC_COLORDDB );
48195 MOV ECX, [EAX].FHandle
48196 JECXZ @@make_handle
48197 MOV AL, 1
48199 @@make_handle:
48200 MOV ECX, [EAX].fImgWidth
48201 JECXZ @@ret_ECX
48202 MOV EDX, ECX
48203 MOV ECX, [EAX].fImgHeight
48204 JECXZ @@ret_ECX
48205 PUSH EBX
48206 XCHG EBX, EAX
48208 PUSH [EBX].FAllocBy
48209 PUSH 0
48210 MOVZX EAX, [EBX].FColors
48211 MOVZX EAX, byte ptr [ColorFlags+EAX]
48212 CMP [EBX].FMasked, 0
48213 JZ @@flags_ready
48214 {$IFDEF PARANOIA}
48215 DB $0C, $01
48216 {$ELSE}
48217 OR AL, 1
48218 {$ENDIF}
48219 @@flags_ready:
48220 PUSH EAX
48221 PUSH ECX
48222 PUSH EDX
48223 CALL ImageList_Create
48224 MOV [EBX].FHandle, EAX
48225 XCHG ECX, EAX
48226 POP EBX
48227 @@ret_ECX:
48228 TEST ECX, ECX
48229 SETNZ AL
48230 end;
48231 {$ELSE ASM_VERSION} //Pascal
48232 function TImageList.HandleNeeded: Boolean;
48233 const ColorFlags : array[ TImageListColors ] of Byte = ( ILC_COLOR,
48234 ILC_COLOR4, ILC_COLOR8, ILC_COLOR16, ILC_COLOR24,
48235 ILC_COLOR32, ILC_COLORDDB, 0 );
48236 var Flags : DWord;
48237 begin
48238 Result := True;
48239 if FHandle <> 0 then Exit;
48240 Result := False;
48241 if ImgWidth = 0 then Exit;
48242 if ImgHeight = 0 then Exit;
48243 Flags := ColorFlags[ FColors ];
48244 if Masked then
48245 Flags := Flags or ILC_MASK;
48246 FHandle := ImageList_Create( ImgWidth, ImgHeight, Flags, 0, FAllocBy );
48247 if fBkColor <> clNone then
48248 SetBkColor( fBkColor );
48249 Result := FHandle <> 0;
48250 end;
48251 {$ENDIF ASM_VERSION}
48254 //[function TImageList.ImgRect]
48255 function TImageList.ImgRect(Idx: Integer): TRect;
48256 var II : TImageInfo;
48257 begin
48258 Result := MakeRect( 0, 0, 0, 0 );
48259 if FHandle = 0 then Exit;
48260 if ImageList_GetImageInfo( FHandle, Idx, II ) then
48261 Result := II.rcImage;
48262 end;
48264 {$IFDEF ASM_noVERSION}
48265 //[function TImageList.LoadBitmap]
48266 function TImageList.LoadBitmap(ResourceName: PChar;
48267 TranspColor: TColor): Boolean;
48269 PUSH EBX
48270 XCHG EBX, EAX
48271 XCHG EAX, ECX //TranspColor
48272 PUSH EDX
48273 CMP EAX, clNone
48274 JNE @@2rgb
48275 OR EAX, -1
48276 JMP @@tranColorReady
48277 @@2rgb:
48278 CALL Color2RGB
48279 @@tranColorReady:
48280 POP EDX
48281 PUSH EAX
48282 PUSH [EBX].fAllocBy
48283 PUSH [EBX].fImgWidth
48284 PUSH EDX
48285 PUSH [hInstance]
48286 CALL ImageList_LoadBitmap
48287 TEST EAX, EAX
48288 JZ @@exit
48289 XCHG EDX, EAX
48290 XCHG EAX, EBX
48291 CALL SetHandle
48292 MOV AL, 1
48293 @@exit: POP EBX
48294 end;
48295 {$ELSE ASM_VERSION} //Pascal
48296 function TImageList.LoadBitmap(ResourceName: PChar;
48297 TranspColor: TColor): Boolean;
48298 var NewHandle : THandle;
48299 TranColr: TColor;
48300 begin
48301 TranColr := TranspColor;
48302 if TranColr = clNone then TranColr := TColor( CLR_NONE )
48303 else TranColr := Color2RGB( TranColr );
48304 NewHandle := ImageList_LoadBitmap( hInstance, ResourceName,
48305 ImgWidth, AllocBy, TranColr );
48306 //ImageList_GetIconSize( NewHandle, fImgWidth, fImgHeight );
48307 Result := NewHandle <> 0;
48308 if Result then
48309 Handle := NewHandle;
48310 ImageList_GetIconSize( fHandle, FImgWidth, FImgHeight );
48311 end;
48312 {$ENDIF ASM_VERSION}
48315 //[function TImageList.LoadFromFile]
48316 function TImageList.LoadFromFile(FileName: PChar; TranspColor: TColor;
48317 ImgType: TImageType): Boolean;
48318 const ImgTypes:array[ TImageType ] of DWord = ( IMAGE_BITMAP, IMAGE_ICON, IMAGE_CURSOR );
48319 var NewHandle : THandle;
48320 TranspFlag : DWord;
48321 begin
48322 TranspFlag := 0;
48323 if TranspColor <> clNone then
48324 TranspFlag := LR_LOADTRANSPARENT;
48325 NewHandle := ImageList_LoadImage( hInstance, FileName, ImgWidth, AllocBy, Color2RGB( TranspColor ),
48326 ImgTypes[ ImgType ], LR_LOADFROMFILE or TranspFlag );
48327 Result := NewHandle <> 0;
48328 if Result then
48329 Handle := NewHandle;
48330 end;
48333 //[function TImageList.LoadSystemIcons]
48334 function TImageList.LoadSystemIcons(SmallIcons: Boolean): Boolean;
48335 var NewHandle : THandle;
48336 FileInfo : TSHFileInfo;
48337 Flags : DWord;
48338 begin
48339 OleInit;
48340 Flags := SHGFI_SYSICONINDEX;
48341 if SmallIcons then
48342 Flags := Flags or SHGFI_SMALLICON;
48343 NewHandle := SHGetFileInfo( '', 0, FileInfo, Sizeof( FileInfo ), Flags );
48344 Result := NewHandle <> 0;
48345 if Result then
48346 begin
48347 Handle := NewHandle;
48348 FShareImages := True;
48349 end;
48350 end;
48353 //[function TImageList.Merge]
48354 function TImageList.Merge(Idx: Integer; ImgList2: PImageList; Idx2, X,
48355 Y: Integer): PImageList;
48356 var L : THandle;
48357 begin
48358 Result := nil;
48359 //if FHandle = 0 then Exit;
48360 L := ImageList_Merge( FHandle, Idx, ImgList2.Handle, Idx2, X, Y );
48361 if L <> 0 then
48362 begin
48363 Result := NewImageList( fControl );
48364 Result.Handle := L;
48365 end;
48366 end;
48369 //[function TImageList.Replace]
48370 function TImageList.Replace(Idx: Integer; Bmp, Msk: HBitmap): Boolean;
48371 begin
48372 Result := False;
48373 if FHandle = 0 then Exit;
48374 Result := ImageList_Replace( FHandle, Idx, Bmp, Msk );
48375 end;
48378 //[function TImageList.ReplaceIcon]
48379 function TImageList.ReplaceIcon(Idx: Integer; Ico: HIcon): Boolean;
48380 begin
48381 Result := False;
48382 if FHandle = 0 then Exit;
48383 Result := ImageList_ReplaceIcon( FHandle, Idx, Ico ) >= 0;
48384 end;
48387 //[procedure TImageList.SetAllocBy]
48388 procedure TImageList.SetAllocBy(const Value: Integer);
48389 begin
48390 if FHandle <> 0 then Exit;
48391 // AllocBy can be changed only before adding images
48392 // and creating image list handle
48393 FAllocBy := Value;
48394 end;
48397 //[procedure TImageList.SetBkColor]
48398 procedure TImageList.SetBkColor(const Value: TColor);
48399 begin
48400 fBkColor := Value;
48401 if fHandle <> 0 then
48402 ImageList_SetBkColor( FHandle, Color2RGB( Value ) );
48403 end;
48406 //[procedure TImageList.SetColors]
48407 procedure TImageList.SetColors(const Value: TImageListColors);
48408 begin
48409 if FHandle <> 0 then Exit;
48410 FColors := Value;
48411 end;
48413 {$IFDEF ASM_VERSION}
48414 //[procedure TImageList.SetHandle]
48415 procedure TImageList.SetHandle(const Value: THandle);
48417 PUSH EBX
48418 XCHG EBX, EAX
48419 MOV ECX, [EBX].FHandle
48420 CMP ECX, EDX
48421 JZ @@exit
48422 JECXZ @@set_handle
48423 CMP [EBX].fShareImages, 0
48424 JNZ @@set_handle
48425 PUSH EDX
48426 PUSH ECX
48427 CALL ImageList_Destroy
48428 POP EDX
48430 @@set_handle:
48431 MOV [EBX].FHandle, EDX
48432 TEST EDX, EDX
48433 JZ @@set_sz0
48434 LEA EAX, [EBX].FImgHeight
48435 PUSH EAX
48436 LEA EAX, [EBX].FImgWidth
48437 PUSH EAX
48438 PUSH EDX
48439 CALL ImageList_GetIconSize
48440 JMP @@exit
48442 @@set_sz0:
48443 MOV [EBX].fImgWidth, EDX
48444 MOV [EBX].fImgHeight, EDX
48446 @@exit:
48447 POP EBX
48448 end;
48449 {$ELSE ASM_VERSION} //Pascal
48450 procedure TImageList.SetHandle(const Value: THandle);
48451 begin
48452 if FHandle = Value then Exit;
48453 if (FHandle <> 0) and not FShareImages then
48454 ImageList_Destroy( FHandle );
48455 FHandle := Value;
48456 if FHandle <> 0 then
48457 ImageList_GetIconSize( FHandle, FImgWidth, FImgHeight )
48458 else
48459 begin
48460 FImgWidth := 0;
48461 FImgHeight := 0;
48462 end;
48463 //FBkColor := ImageList_GetBkColor( FHandle );
48464 end;
48465 {$ENDIF ASM_VERSION}
48467 //[procedure TImageList.SetImgHeight]
48468 procedure TImageList.SetImgHeight(const Value: Integer);
48469 begin
48470 if FHandle <> 0 then Exit;
48471 FImgHeight := Value;
48472 end;
48474 //[procedure TImageList.SetImgWidth]
48475 procedure TImageList.SetImgWidth(const Value: Integer);
48476 begin
48477 if FHandle <> 0 then Exit;
48478 FImgWidth := Value;
48479 end;
48481 //[procedure TImageList.SetMasked]
48482 procedure TImageList.SetMasked(const Value: Boolean);
48483 begin
48484 if FHandle <> 0 then Exit;
48485 FMasked := Value;
48486 end;
48489 //[function TImageList.GetOverlay]
48490 function TImageList.GetOverlay(Idx: TImgLOVrlayIdx): Integer;
48491 begin
48492 Result := fOverlay[ Idx ];
48493 end;
48495 //[procedure TImageList.SetOverlay]
48496 procedure TImageList.SetOverlay(Idx: TImgLOVrlayIdx; const Value: Integer);
48497 begin
48498 if ImageList_SetOverlayImage( fHandle, Value, Idx shl 8 ) then
48499 fOverlay[ Idx ] := Value;
48500 end;
48502 //[procedure TImageList.StretchDraw]
48503 procedure TImageList.StretchDraw(Idx: Integer; DC: HDC; const Rect: TRect);
48504 begin
48505 if FHandle = 0 then Exit;
48506 ImageList_DrawEx( FHandle, Idx, DC, Rect.Left, Rect.Top,
48507 Rect.Right- Rect.Left, Rect.Bottom-Rect.Top,
48508 BkColor, BlendColor, GetDrawStyle );
48509 end;
48512 //[function GetImgListSize]
48513 function GetImgListSize( Sender: PControl; Size: Integer ): PImageList;
48514 begin
48515 if Size > 16 then
48516 Result := Sender.fCtlImageListNormal
48517 else
48518 Result := Sender.fCtlImageListSml;
48519 if Result <> nil then
48520 begin
48521 if Result.fImgWidth = 0 then
48522 Result.ImgWidth := Size;
48523 if Result.fImgHeight = 0 then
48524 Result.ImgHeight := Size;
48525 //if (Result.FImgWidth <> Size) or (Result.FImgHeight <> Size) then
48526 // Result := nil;
48527 end;
48528 if Result = nil then
48529 begin
48530 Result := Sender.fImageList;
48531 while Result <> nil do
48532 begin
48533 if (Result.FImgWidth = Size) and (Result.FImgHeight = Size) then
48534 break;
48535 Result := Result.fNext;
48536 end;
48537 end;
48538 end;
48541 //[function TControl.GetImgListIdx]
48542 function TControl.GetImgListIdx(const Index: Integer): PImageList;
48543 begin
48544 if Index <> 0 then
48545 Result := GetImgListSize( @Self, Index )
48546 else
48547 begin
48548 Result := fCtlImgListState;
48549 if Result = nil then
48550 begin
48551 Result := fImageList;
48552 while Result <> nil do
48553 begin
48554 if (Result <> GetImgListIdx( 16 )) and (Result <> GetImgListIdx( 32 )) then
48555 break;
48556 Result := Result.fNext;
48557 end;
48558 end;
48559 end;
48560 end;
48563 //[procedure TControl.SetImgListIdx]
48564 procedure TControl.SetImgListIdx(const Index: Integer;
48565 const Value: PImageList);
48566 begin
48568 if Value <> nil then
48569 begin
48570 if Index <> 0 then
48571 if (Value.ImgWidth = 0) or (Value.ImgHeight = 0) then
48572 begin
48573 Value.ImgWidth := Index;
48574 Value.ImgHeight := Index;
48575 end;
48576 end;
48578 case Index of
48579 32: fCtlImageListNormal := Value;
48580 16: fCtlImageListSml := Value;
48581 else fCtlImgListState := Value;
48582 end;
48583 ApplyImageLists2Control( @Self );
48584 end;
48586 { -- list view -- }
48588 //[function WndProcEndLabelEdit]
48589 function WndProcEndLabelEdit( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
48590 var NMhdr: PNMHdr;
48591 LVDisp: PLVDispInfo;
48592 {$IFNDEF _FPC}
48593 {$IFNDEF _D2}
48594 {$IFDEF UNICODE_CTRLS}
48595 LVDispW: PLVDispInfoW;
48596 {$ENDIF UNICODE_CTRLS}
48597 {$ENDIF _D2}
48598 {$ENDIF _FPC}
48599 Flag: Boolean;
48600 begin
48601 Result := False;
48602 if Msg.message = WM_NOTIFY then
48603 begin
48604 NMHdr := Pointer( Msg.lParam );
48605 case NMHdr.code of
48606 LVN_ENDLABELEDIT {$IFDEF UNICODE_CTRLS}, LVN_ENDLABELEDITW {$ENDIF UNICODE_CTRLS}:
48607 begin
48608 LVDisp := Pointer( Msg.lParam );
48609 Result := True;
48610 if LVDisp.item.pszText = nil then Exit;
48611 Rslt := 1;
48612 if assigned( Self_.fOnEditLVItem ) then
48613 begin
48614 {$IFNDEF _FPC}
48615 {$IFNDEF _D2}
48616 {$IFDEF UNICODE_CTRLS}
48617 if NMHdr.code = LVN_ENDLABELEDITW then
48618 begin
48619 LVDispW := Pointer( LVDisp );
48620 Flag := Self_.fOnEditLVItem( Self_, LVDispW.item.iItem,
48621 LVDispW.item.iSubItem, PChar( LVDispW.item.pszText ) );
48622 end else
48623 {$ENDIF UNICODE_CTRLS}
48624 {$ENDIF _D2}
48625 {$ENDIF _FPC}
48626 Flag := Self_.fOnEditLVItem( Self_, LVDisp.item.iItem,
48627 LVDisp.item.iSubItem, LVDisp.item.pszText );
48628 if Flag then Rslt := 1
48629 else Rslt := 0;
48630 end;
48631 end;
48632 end;
48633 end;
48634 end;
48636 //[procedure TControl.SetOnEditLVItem]
48637 procedure TControl.SetOnEditLVItem(const Value: TOnEditLVItem);
48638 begin
48639 fOnEditLVITem := Value;
48640 AttachProc( WndProcEndLabelEdit );
48641 end;
48644 //[procedure TControl.LVColAdd]
48645 procedure TControl.LVColAdd(const aText: String; aalign: TTextAlign;
48646 aWidth: Integer);
48647 begin
48648 ////////////////////////////////////////////////////
48649 //LVColInsert( fLVColCount + 1, aText, aalign, aWidth );
48650 //////////////////////////////////////////////////////
48651 LVColInsert( fLVColCount, aText, aalign, aWidth );// 21.10.2001
48652 ////////////////////////////////////////////////////
48653 end;
48655 {$IFNDEF _FPC}
48656 {$IFNDEF _D2}
48657 //[procedure TControl.LVColAddW]
48658 procedure TControl.LVColAddW(const aText: WideString; aalign: TTextAlign;
48659 aWidth: Integer);
48660 begin
48661 LVColInsertW( fLVColCount, aText, aalign, aWidth );
48662 end;
48663 {$ENDIF _D2}
48664 {$ENDIF _FPC}
48666 //****************** changed by Mike Gerasimov
48667 //[procedure TControl.LVColInsert]
48668 procedure TControl.LVColInsert(ColIdx: Integer; const aText: String;
48669 aAlign: TTextAlign; aWidth: Integer);
48670 var LVColData: TLVColumn;
48671 begin
48672 LVColData.mask := LVCF_FMT or LVCF_TEXT;
48673 if ImageListSmall <> nil then
48674 LVColData.mask := LVColData.mask; // or LVCF_IMAGE ;
48675 LVColData.iImage := -1;
48676 LVColData.fmt := Ord( aAlign );
48677 if aWidth < 0 then
48678 begin
48679 aWidth := -aWidth;
48680 LVColData.fmt := LVColData.fmt or LVCFMT_BITMAP_ON_RIGHT;
48681 end;
48682 LVColData.cx := aWidth;
48683 if aWidth > 0 then
48684 LVColData.mask := LVColData.mask or LVCF_WIDTH;
48685 LVColData.pszText := PChar( aText );
48686 if Perform( LVM_INSERTCOLUMN, ColIdx, Integer( @LVColData ) ) >= 0 then
48687 Inc( fLVColCount );
48688 end;
48690 {$IFNDEF _FPC}
48691 {$IFNDEF _D2}
48692 //[procedure TControl.LVColInsertW]
48693 procedure TControl.LVColInsertW(ColIdx: Integer; const aText: WideString;
48694 aAlign: TTextAlign; aWidth: Integer);
48695 var LVColData: TLVColumnW;
48696 begin
48697 LVColData.mask := LVCF_FMT or LVCF_TEXT;
48698 if ImageListSmall <> nil then
48699 LVColData.mask := LVColData.mask; // or LVCF_IMAGE ;
48700 LVColData.iImage := -1;
48701 LVColData.fmt := Ord( aAlign );
48702 if aWidth < 0 then
48703 begin
48704 aWidth := -aWidth;
48705 LVColData.fmt := LVColData.fmt or LVCFMT_BITMAP_ON_RIGHT;
48706 end;
48707 LVColData.cx := aWidth;
48708 if aWidth > 0 then
48709 LVColData.mask := LVColData.mask or LVCF_WIDTH;
48710 LVColData.pszText := PWideChar( aText );
48711 if Perform( LVM_INSERTCOLUMNW, ColIdx, Integer( @LVColData ) ) >= 0 then
48712 Inc( fLVColCount );
48713 end;
48714 {$ENDIF _D2}
48715 {$ENDIF _FPC}
48717 //[function TControl.GetLVColText]
48718 function TControl.GetLVColText(Idx: Integer): String;
48719 var Buf: array[ 0..4095 ] of Char;
48720 LC: TLVColumn;
48721 begin
48722 LC.mask := LVCF_TEXT;
48723 LC.pszText := @ Buf[ 0 ];
48724 LC.cchTextMax := Sizeof( Buf );
48725 Buf[ 0 ] := #0;
48726 Perform( LVM_GETCOLUMN, Idx, Integer( @ LC ) );
48727 Result := Buf;
48728 end;
48730 //[procedure TControl.SetLVColText]
48731 procedure TControl.SetLVColText(Idx: Integer; const Value: String);
48732 var LC: TLVColumn;
48733 begin
48734 FillChar( LC, Sizeof( LC ), 0 ); {Alexey (Lecha2002)}
48735 LC.mask := LVCF_TEXT;
48736 LC.pszText := '';
48737 if Value <> '' then
48738 LC.pszText := @ Value[ 1 ];
48739 Perform( LVM_SETCOLUMN, Idx, Integer( @ LC ) );
48740 end;
48742 {$IFNDEF _FPC}
48743 {$IFNDEF _D2}
48744 //[function TControl.GetLVColTextW]
48745 function TControl.GetLVColTextW(Idx: Integer): WideString;
48746 var Buf: array[ 0..4095 ] of WideChar;
48747 LC: TLVColumnW;
48748 begin
48749 LC.mask := LVCF_TEXT;
48750 LC.pszText := @ Buf[ 0 ];
48751 LC.cchTextMax := High( Buf ) + 1;
48752 Buf[ 0 ] := #0;
48753 Perform( LVM_GETCOLUMNW, Idx, Integer( @ LC ) );
48754 Result := Buf;
48755 end;
48757 //[procedure TControl.SetLVColTextW]
48758 procedure TControl.SetLVColTextW(Idx: Integer; const Value: WideString);
48759 var LC: TLVColumnW;
48760 begin
48761 FillChar( LC, Sizeof( LC ), 0 );
48762 LC.mask := LVCF_TEXT;
48763 LC.pszText := '';
48764 if Value <> '' then
48765 LC.pszText := @ Value[ 1 ];
48766 Perform( LVM_SETCOLUMNW, Idx, Integer( @ LC ) );
48767 end;
48768 {$ENDIF _D2}
48769 {$ENDIF _FPC}
48771 //[function TControl.GetLVColalign]
48772 function TControl.GetLVColalign(Idx: Integer): TTextAlign;
48773 const Formats: array[ 0..2 ] of TTextAlign = ( taLeft, taRight, taCenter );
48774 var LC: TLVColumn;
48775 begin
48776 FillChar( LC, Sizeof( LC ), 0 ); {Alexey (Lecha2002)}
48777 LC.mask := LVCF_FMT;
48778 Perform( LVM_GETCOLUMN, Idx, Integer( @ LC ) );
48779 Result := Formats[ LC.fmt and LVCFMT_JUSTIFYMASK ];
48780 end;
48782 //[procedure TControl.SetLVColalign]
48783 procedure TControl.SetLVColalign(Idx: Integer; const Value: TTextAlign);
48784 const FormatFlags: array[ TTextAlign ] of BYTE = ( LVCFMT_LEFT, LVCFMT_RIGHT,
48785 LVCFMT_CENTER );
48786 var LC: TLVColumn;
48787 begin
48788 FillChar( LC, Sizeof( LC ), 0 ); {Alexey (Lecha2002)}
48789 LC.mask := LVCF_FMT;
48790 Perform( LVM_GETCOLUMN, Idx, Integer( @ LC ) );
48791 LC.fmt := LC.fmt and not LVCFMT_JUSTIFYMASK or FormatFlags[ Value ];
48792 Perform( LVM_SETCOLUMN, Idx, Integer( @ LC ) );
48793 end;
48795 //[function TControl.GetLVColEx]
48796 function TControl.GetLVColEx(Idx: Integer; const Index: Integer): Integer;
48797 var LC: TLVColumn;
48798 begin
48799 FillChar( LC, Sizeof( LC ), 0 ); {Alexey (Lecha2002)}
48800 LC.mask := LoWord( Index );
48801 Perform( LVM_GETCOLUMN, Idx, Integer( @ LC ) );
48802 Result := PDWORD( Integer( @ LC ) + HiWord( Index ) )^;
48803 end;
48805 //********************** changed by Mike Gerasimov
48806 //[procedure TControl.SetLVColEx]
48807 procedure TControl.SetLVColEx(Idx: Integer; const Index: Integer;
48808 const Value: Integer);
48809 var LC: TLVColumn;
48810 begin
48811 FillChar(LC,SizeOf(LC),0); // Added Line
48812 LC.mask := LoWord( Index );
48813 if HiWord( Index ) = 24 then // Added Line
48814 begin // Added Line
48815 LC.mask := LC.mask or LVCF_FMT; // Added Line
48816 if Value <>-1 Then // Added Line
48817 LC.fmt := LC.fmt or LVCFMT_IMAGE or LVCFMT_COL_HAS_IMAGES; // Added Line
48818 end;
48819 PDWORD( Integer( @ LC ) + HiWord( Index ) )^ := Value;
48820 Perform( LVM_SETCOLUMN, Idx, Integer( @ LC ) );
48821 end;
48824 //[function TControl.LVAdd]
48825 function TControl.LVAdd(const aText: String; ImgIdx: Integer;
48826 State: TListViewItemState; StateImgIdx, OverlayImgIdx: Integer;
48827 Data: DWORD): Integer;
48828 begin
48829 Result := LVInsert( MaxInt {Count}, aText, ImgIdx, State, StateImgIdx, OverlayImgIdx, Data );
48830 end;
48833 //[function TControl.LVInsert]
48834 function TControl.LVInsert(Idx: Integer; const aText: String;
48835 ImgIdx: Integer; State: TListViewItemState; StateImgIdx, OverlayImgIdx: Integer;
48836 Data: DWORD): Integer;
48837 const
48838 LVM_REDRAWITEMS = LVM_FIRST + 21;
48839 var LVI: TLVItem;
48840 begin
48841 LVI.mask := LVIF_TEXT or LVIF_IMAGE or LVIF_PARAM or LVIF_STATE
48842 or LVIF_DI_SETITEM;
48843 LVI.iItem := Idx;
48844 LVI.iSubItem := 0;
48845 LVI.state := 0;
48846 if lvisBlend in State then
48847 LVI.state := LVIS_CUT;
48848 if lvisHighlight in State then
48849 LVI.state := LVI.state or LVIS_DROPHILITED;
48850 if lvisFocus in State then
48851 LVI.state := LVI.state or LVIS_FOCUSED;
48852 if lvisSelect in State then
48853 LVI.state := LVI.state or LVIS_SELECTED;
48854 LVI.stateMask := $FFFF;
48855 if StateImgIdx <> 0 then
48856 LVI.state := LVI.state or ((StateImgIdx and $F) shl 12);
48857 if OverlayImgIdx <> 0 then
48858 LVI.state := LVI.state or ((OverlayImgIdx and $F) shl 8);
48859 LVI.pszText := PChar( aText );
48860 LVI.iImage := ImgIdx;
48861 LVI.lParam := Data;
48862 Result := Perform( LVM_INSERTITEM, 0, Integer( @LVI ) );
48863 //Perform( LVM_REDRAWITEMS, Idx, Idx );
48864 end;
48867 //[procedure TControl.LVSetItem]
48868 procedure TControl.LVSetItem(Idx, Col: Integer; const aText: String;
48869 ImgIdx: Integer; State: TListViewItemState; StateImgIdx,
48870 OverlayImgIdx: Integer; Data: DWORD);
48871 var LVI: TLVItem;
48872 I: Integer;
48873 begin
48874 LVI.mask := LVIF_TEXT or {LVIF_STATE or} LVIF_DI_SETITEM;
48875 if Col = 0 then
48876 begin
48877 LVI.mask := LVIF_TEXT or LVIF_STATE or LVIF_PARAM
48878 or LVIF_DI_SETITEM;
48879 if ImgIdx <> I_SKIP then
48880 LVI.mask := LVI.mask or LVIF_IMAGE;
48881 end;
48882 if ImgIdx < I_SKIP then
48883 LVI.mask := LVIF_TEXT or LVIF_DI_SETITEM;
48884 LVI.iItem := Idx;
48885 LVI.iSubItem := Col;
48886 LVI.state := 0;
48887 if lvisBlend in State then
48888 LVI.state := LVIS_CUT;
48889 if lvisHighlight in State then
48890 LVI.state := LVI.state or LVIS_DROPHILITED;
48891 if lvisFocus in State then
48892 LVI.state := LVI.state or LVIS_FOCUSED;
48893 if lvisSelect in State then
48894 LVI.state := LVI.state or LVIS_SELECTED;
48895 LVI.stateMask := $FFFF;
48896 if StateImgIdx <> 0 then
48897 LVI.state := LVI.state or ((StateImgIdx and $F) shl 12);
48898 if StateImgIdx < 0 {= I_SKIP} then
48899 LVI.stateMask := $F0FF;
48900 if OverlayImgIdx <> 0 then
48901 LVI.state := LVI.state or ((OverlayImgIdx and $F) shl 8);
48902 if OverlayImgIdx < 0 {=I_SKIP} then
48903 LVI.stateMask := LVI.stateMask and $FFF;
48904 LVI.pszText := PChar( aText );
48905 LVI.iImage := ImgIdx;
48906 LVI.lParam := Data;
48907 I := Perform( LVM_SETITEM, 0, Integer( @LVI ) );
48908 if (I = 0) and (Col = 0) then
48909 Assert( False, 'Can not set item ' );
48910 end;
48913 //[procedure LVGetItem]
48914 procedure LVGetItem( Sender: PControl; Idx, Col: Integer; var LVI: TLVItem;
48915 TextBuf: PChar; TextBufSize: Integer );
48916 begin
48917 LVI.mask := LVIF_STATE or LVIF_PARAM or LVIF_IMAGE;
48918 if Col > 0 then
48919 if not (lvoSubItemImages in Sender.fLVOptions) then
48920 LVI.mask := LVIF_STATE or LVIF_PARAM;
48921 LVI.iItem := Idx;
48922 LVI.iSubItem := Col;
48923 LVI.pszText := TextBuf;
48924 LVI.cchTextMax := TextBufSize;
48925 if TextBufSize <> 0 then
48926 LVI.mask := LVI.mask or LVIF_TEXT;
48927 Sender.Perform( LVM_GETITEM, 0, Integer( @LVI ) );
48928 end;
48930 {$IFNDEF _FPC}
48931 {$IFNDEF _D2}
48932 //[procedure LVGetItemW]
48933 procedure LVGetItemW( Sender: PControl; Idx, Col: Integer; var LVI: TLVItemW;
48934 TextBuf: PWideChar; TextBufSize: Integer );
48935 begin
48936 LVI.mask := LVIF_STATE or LVIF_PARAM or LVIF_IMAGE;
48937 if Col > 0 then
48938 if not (lvoSubItemImages in Sender.fLVOptions) then
48939 LVI.mask := LVIF_STATE or LVIF_PARAM;
48940 LVI.iItem := Idx;
48941 LVI.iSubItem := Col;
48942 LVI.pszText := TextBuf;
48943 LVI.cchTextMax := TextBufSize;
48944 if TextBufSize <> 0 then
48945 LVI.mask := LVI.mask or LVIF_TEXT;
48946 Sender.Perform( LVM_GETITEMW, 0, Integer( @LVI ) );
48947 end;
48948 {$ENDIF _D2}
48949 {$ENDIF _FPC}
48952 //[function TControl.LVGetItemImgIdx]
48953 function TControl.LVGetItemImgIdx(Idx: Integer): Integer;
48954 var LVI: TLVItem;
48955 begin
48956 LVI.iImage := -1;//= Result if image is not assigned {Andrzej Kubaszek}
48957 LVGetItem( @Self, Idx, 0, LVI, nil, 0 );
48958 Result := LVI.iImage;
48959 end;
48962 //[procedure TControl.LVSetItemImgIdx]
48963 procedure TControl.LVSetItemImgIdx(Idx: Integer; const Value: Integer);
48964 var LVI: TLVItem;
48965 begin
48966 LVGetItem( @Self, Idx, 0, LVI, nil, 0 );
48967 LVI.iImage := Value;
48968 Perform( LVM_SETITEM, 0, Integer( @LVI ) );
48969 end;
48972 //[function TControl.LVGetItemText]
48973 function TControl.LVGetItemText(Idx, Col: Integer): String;
48974 var LVI: TLVItem;
48975 TextBuf: PChar;
48976 BufSize: DWORD;
48977 begin
48978 BufSize := 0;
48979 TextBuf := nil;
48980 repeat
48981 if TextBuf <> nil then
48982 FreeMem( TextBuf );
48983 BufSize := BufSize * 2 + 100; // to vary in asm version
48984 GetMem( TextBuf, BufSize );
48985 TextBuf[ 0 ] := #0;
48986 LVGetItem( @Self, Idx, Col, LVI, TextBuf, BufSize );
48987 until StrLen( TextBuf ) < BufSize - 1;
48988 Result := TextBuf;
48989 FreeMem( TextBuf );
48990 end;
48993 //[procedure TControl.LVSetItemText]
48994 procedure TControl.LVSetItemText(Idx, Col: Integer; const Value: String);
48995 var LVI: TLVItem;
48996 begin
48997 LVI.iSubItem := Col;
48998 LVI.pszText := PChar( Value );
48999 Perform( LVM_SETITEMTEXT, Idx, Integer( @LVI ) );
49000 end;
49002 {$IFNDEF _FPC}
49003 {$IFNDEF _D2}
49004 //[function TControl.LVGetItemTextW]
49005 function TControl.LVGetItemTextW(Idx, Col: Integer): WideString;
49006 var LVI: TLVItemW;
49007 TextBuf: PWideChar;
49008 BufSize: DWORD;
49009 begin
49010 BufSize := 0;
49011 TextBuf := nil;
49012 repeat
49013 if TextBuf <> nil then
49014 FreeMem( TextBuf );
49015 BufSize := BufSize * 2 + 100; // to vary in asm version
49016 GetMem( TextBuf, BufSize * 2 );
49017 TextBuf[ 0 ] := #0;
49018 LVGetItemW( @Self, Idx, Col, LVI, TextBuf, BufSize );
49019 until DWORD( WStrLen( TextBuf ) ) < BufSize - 1;
49020 Result := TextBuf;
49021 FreeMem( TextBuf );
49022 end;
49024 //[procedure TControl.LVSetItemTextW]
49025 procedure TControl.LVSetItemTextW(Idx, Col: Integer;
49026 const Value: WideString);
49027 var LVI: TLVItemW;
49028 begin
49029 LVI.iSubItem := Col;
49030 LVI.pszText := PWideChar( Value );
49031 Perform( LVM_SETITEMTEXTW, Idx, Integer( @LVI ) );
49032 end;
49033 {$ENDIF _D2}
49034 {$ENDIF _FPC}
49037 //[procedure TControl.LVColDelete]
49038 procedure TControl.LVColDelete(ColIdx: Integer);
49039 begin
49040 Perform( LVM_DELETECOLUMN, ColIdx, 0 );
49041 if fLVColCount > 0 then
49042 Dec( fLVColCount );
49043 end;
49046 //[procedure TControl.SetLVOptions]
49047 procedure TControl.SetLVOptions(const Value: TListViewOptions);
49048 begin
49049 if fLVOptions = Value then Exit;
49050 fLVOptions := Value;
49051 ApplyImageLists2ListView( @Self );
49052 PostMessage( fHandle, WM_SIZE, 0, 0 ); // to restore scrollers (otherwise its are lost)
49053 end;
49056 //[procedure TControl.SetLVStyle]
49057 procedure TControl.SetLVStyle(const Value: TListViewStyle);
49058 begin
49059 if fLVStyle = Value then Exit;
49060 fLVStyle := Value;
49061 ApplyImageLists2ListView( @Self );
49062 end;
49064 {$IFDEF ASM_VERSION}
49065 //[function TControl.Perform]
49066 function TControl.Perform(msgcode: DWORD; wParam, lParam: Integer): Integer; stdcall;
49068 PUSH [lParam]
49069 PUSH [wParam]
49070 PUSH [msgcode]
49071 MOV EAX, [EBP+8]
49072 CALL TControl.GetWindowHandle
49073 PUSH EAX
49074 CALL Windows.SendMessage
49075 end;
49076 {$ELSE ASM_VERSION} //Pascal
49077 function TControl.Perform(msgcode: DWORD; wParam, lParam: Integer): Integer; stdcall;
49078 begin
49079 Result := SendMessage( GetWindowHandle, msgcode, wParam, lParam );
49080 end;
49081 {$ENDIF ASM_VERSION}
49083 {$IFDEF ASM_VERSION}
49084 //[function TControl.GetChildCount]
49085 function TControl.GetChildCount: Integer;
49087 MOV EAX, [EAX].fChildren
49088 MOV EAX, [EAX].TList.fCount
49089 end;
49090 {$ELSE ASM_VERSION} //Pascal
49091 function TControl.GetChildCount: Integer;
49092 begin
49093 Result := fChildren.fCount;
49094 end;
49095 {$ENDIF ASM_VERSION}
49097 //[procedure TControl.LVDelete]
49098 procedure TControl.LVDelete(Idx: Integer);
49099 begin
49100 Perform( LVM_DELETEITEM, Idx, 0 );
49101 end;
49103 //[procedure TControl.LVEditItemLabel]
49104 procedure TControl.LVEditItemLabel(Idx: Integer);
49105 begin
49106 Perform( LVM_EDITLABEL, Idx, 0 );
49107 end;
49110 //[function TControl.LVItemRect]
49111 function TControl.LVItemRect(Idx: Integer; Part: TGetLVItemPart): TRect;
49112 const Parts: array[ TGetLVItemPart ] of Byte = (
49113 LVIR_BOUNDS, LVIR_ICON, LVIR_LABEL, LVIR_SELECTBOUNDS );
49114 begin
49115 Result := MakeRect( Parts[ Part ], 0, 0, 0 );
49116 if Perform( LVM_GETITEMRECT, Idx, Integer( @Result ) ) = 0 then
49117 Result := MakeRect( 0, 0, 0, 0 );
49118 end;
49120 //[function TControl.LVSubItemRect]
49121 function TControl.LVSubItemRect(Idx, ColIdx: Integer): TRect;
49122 var Hdr: HWnd;
49123 R, R1: TRect;
49124 ClassNameBuf: array[ 0..31 ] of Char;
49125 HdItem: THDItem;
49126 begin
49127 Result.Top := ColIdx; // + 1; error in MSDN ?
49128 Result.Left := LVIR_BOUNDS;
49129 if Perform( LVM_GETSUBITEMRECT, Idx, Integer( @Result ) ) <> 0 then
49130 Exit;
49131 Result := MakeRect( 0, 0, 0, 0 );
49132 if ColIdx > 0 then R := LVSubItemRect( Idx, ColIdx - 1 )
49133 else R := LVItemRect( Idx, lvipBounds );
49134 if (R.Left = 0) and (R.Right = 0) and
49135 (R.Top = 0) and (R.Bottom = 0) then Exit;
49136 Hdr := GetWindow( GetWindowHandle, GW_CHILD );
49137 if Hdr <> 0 then
49138 begin
49139 if GetClassName( Hdr, ClassNameBuf, 32 ) > 0 then
49140 if ClassNameBuf = 'SysHeader32' then
49141 begin
49142 if ColIdx > 0 then R.Left := R.Right
49143 else R.Left := 0;
49144 R1.Top := 0; R1.Left := 0;
49145 Windows.ClientToScreen( Hdr,{$IFDEF FPC} PPoint( @ R1.Left )^ {$ELSE} R1.TopLeft {$ENDIF} );
49146 Windows.ScreenToClient( fHandle, {$IFDEF FPC} PPoint( @ R1.Left )^ {$ELSE} R1.TopLeft {$ENDIF} );
49147 R1 := R;
49148 HdItem.Mask := HDI_WIDTH;
49149 if SendMessage( Hdr, HDM_GETITEM, ColIdx, Integer( @HdItem ) ) = 0 then Exit;
49150 R1.Right := R1.Left + HdItem.cxy;
49151 Result := R1;
49152 end;
49153 end;
49154 end;
49157 //[function TControl.LVGetItemPos]
49158 function TControl.LVGetItemPos(Idx: Integer): TPoint;
49159 begin
49160 Perform( LVM_GETITEMPOSITION, Idx, Integer( @Result ) );
49161 end;
49164 //[procedure TControl.LVSetItemPos]
49165 procedure TControl.LVSetItemPos(Idx: Integer; const Value: TPoint);
49166 begin
49167 Perform( LVM_SETITEMPOSITION32, Idx, Integer( @Value ) );
49168 end;
49171 //[function TControl.LVItemAtPos]
49172 function TControl.LVItemAtPos(X, Y: Integer): Integer;
49173 var Dummy: TWherePosLVItem;
49174 begin
49175 Result := LVItemAtPosEx( X, Y, Dummy );
49176 end;
49179 //[function TControl.LVItemAtPosEx]
49180 function TControl.LVItemAtPosEx(X, Y: Integer;
49181 var Where: TWherePosLVItem): Integer;
49182 var HTI: TLVHitTestInfo;
49183 begin
49184 HTI.pt.x := X;
49185 HTI.pt.y := Y;
49186 Perform( LVM_HITTEST, 0, Integer( @HTI ) );
49187 Result := HTI.iItem;
49188 Where := lvwpOnColumn;
49189 if HTI.flags = LVHT_ONITEMICON then
49190 Where := lvwpOnIcon
49191 else
49192 if HTI.flags = LVHT_ONITEMLABEL then
49193 Where := lvwpOnLabel
49194 else
49195 if HTI.flags = LVHT_ONITEMSTATEICON then
49196 Where := lvwpOnStateIcon
49197 else
49198 if HTI.flags = LVHT_ONITEM then
49199 Where := lvwpOnItem;
49200 end;
49202 //[procedure TControl.LVMakeVisible]
49203 procedure TControl.LVMakeVisible(Item: Integer; PartiallyOK: Boolean);
49204 begin
49205 if Item < 0 then Exit;
49206 Perform( LVM_ENSUREVISIBLE, Item, Integer( PartiallyOK ) );
49207 end;
49210 //[procedure TControl.LVSetColorByIdx]
49211 procedure TControl.LVSetColorByIdx(const Index: Integer;
49212 const Value: TColor);
49213 var MsgCode: Integer;
49214 ColorValue: TColor;
49215 begin
49216 MsgCode := Index + 1;
49217 case MsgCode of
49218 LVM_SETTEXTCOLOR: fTextColor := Value;
49219 LVM_SETTEXTBKCOLOR: fLVTextBkColor := Value;
49220 LVM_SETBKCOLOR: fColor := Value;
49221 end;
49222 ColorValue := Color2RGB( Value );
49223 Perform( MsgCode, 0, ColorValue );
49224 end;
49226 {$IFDEF F_P}
49227 //[function TControl.LVGetColorByIdx]
49228 function TControl.LVGetColorByIdx(const Index: Integer): TColor;
49229 begin
49230 CASE Index OF
49231 LVM_SETTEXTCOLOR: Result := fTextColor;
49232 LVM_SETTEXTBKCOLOR: Result := fLVTextBkColor;
49233 LVM_SETBKCOLOR: Result := fColor;
49234 END;
49235 end;
49236 {$ENDIF F_P}
49239 //[function TControl.GetIntVal]
49240 function TControl.GetIntVal(const Index: Integer): Integer;
49241 begin
49242 Result := GetItemVal( 0, Index );
49243 end;
49246 //[procedure TControl.SetIntVal]
49247 procedure TControl.SetIntVal(const Index, Value: Integer);
49248 begin
49249 SetItemVal( Value, Index, 0 );
49250 end;
49253 //[function TControl.GetItemVal]
49254 function TControl.GetItemVal(Item: Integer; const Index: Integer): Integer;
49255 begin
49256 Result := Perform( LoWord(Index), Item, 0 );
49257 end;
49259 {$IFDEF ASM_VERSION}
49260 //[procedure TControl.SetItemVal]
49261 procedure TControl.SetItemVal(Item: Integer; const Index: Integer; const Value: Integer);
49263 PUSH EAX
49264 PUSH [Value]
49265 PUSH EDX
49266 MOV EDX, ECX
49267 SHR EDX, 16
49268 JNZ @@1
49269 MOV EDX, ECX
49270 INC EDX
49271 @@1:
49272 MOV EBP, EDX
49273 AND EDX, 7FFFh
49274 PUSH EDX
49275 PUSH EAX
49276 CALL Perform
49277 MOV EAX, EBP
49278 ADD AX, AX
49279 POP EAX
49280 JNB @@2
49281 CALL Invalidate
49282 @@2:
49283 end;
49284 {$ELSE ASM_VERSION} //Pascal
49285 procedure TControl.SetItemVal(Item: Integer; const Index: Integer; const Value: Integer);
49286 var MsgCode: Integer;
49287 begin
49288 MsgCode := HiWord( Index );
49289 if MsgCode = 0 then
49290 MsgCode := Index + 1;
49291 Perform( MsgCode and $7FFF, Item, Value );
49292 if (MsgCode and $8000) <> 0 then
49293 Invalidate;
49294 end;
49295 {$ENDIF ASM_VERSION}
49297 //[procedure TControl.GetSBMinMax]
49298 function TControl.GetSBMinMax: TPoint;
49299 {$IFDEF _D2}
49300 var X, Y: Integer;
49301 {$ENDIF}
49302 begin
49303 if (Handle <> 0) then begin
49304 {$IFDEF _D2}
49305 GetScrollRange(Handle, SB_CTL, X, Y);
49306 Result.X := X;
49307 Result.Y := Y;
49308 {$ELSE}
49309 GetScrollRange(Handle, SB_CTL, Result.X, Result.Y);
49310 {$ENDIF}
49311 Dec(Result.Y, SBPageSize - 1);
49313 else
49314 Result := fSBMinMax;
49315 end;
49317 //[procedure TControl.GetSBPageSize]
49318 function TControl.GetSBPageSize: Integer;
49320 SI: TScrollInfo;
49321 begin
49322 FillChar(SI, SizeOf(SI), 0);
49323 SI.cbSize := SizeOf(SI);
49324 SI.fMask := SIF_PAGE;
49325 SBGetScrollInfo(SI);
49326 Result := SI.nPage;
49327 end;
49329 //[procedure TControl.GetSBPosition]
49330 function TControl.GetSBPosition: Integer;
49331 begin
49332 Result := GetScrollPos(Handle, SB_CTL);
49333 end;
49335 //[procedure TControl.SetSBMax]
49336 procedure TControl.SetSBMax(Value: Longint);
49338 P: TPoint;
49339 begin
49340 fSBMinMax.Y := Value;
49341 if (Handle <> 0) then begin
49342 P := SBMinMax;
49343 P.Y := Value;
49344 SBMinMax := P;
49345 end;
49346 end;
49348 //[procedure TControl.SetSBMin]
49349 procedure TControl.SetSBMin(Value: Longint);
49351 P: TPoint;
49352 begin
49353 fSBMinMax.X := Value;
49354 if (Handle <> 0) then begin
49355 P := SBMinMax;
49356 P.X := Value;
49357 SBMinMax := P;
49358 end;
49359 end;
49361 //[procedure TControl.SetSBPageSize]
49362 procedure TControl.SetSBPageSize(Value: Integer);
49364 SI: TScrollInfo;
49365 begin
49366 fSBPageSize := Value;
49367 if (Handle <> 0) then begin
49368 FillChar(SI, SizeOf(SI), 0);
49369 SI.cbSize := SizeOf(SI);
49370 SI.fMask := SIF_PAGE or SIF_RANGE;
49371 SBGetScrollInfo(SI);
49372 if (SI.nMax = 0) and (SI.nMin = 0) then
49373 SI.nMax := 1;
49374 SI.nMax := SI.nMax - Integer(SI.nPage) + Value;
49375 SI.nPage := Value;
49376 SBSetScrollInfo(SI);
49377 end;
49378 end;
49380 //[procedure TControl.SetSBPosition]
49381 procedure TControl.SetSBPosition(Value: Integer);
49382 begin
49383 fSBPosition := Value;
49384 if (Handle <> 0) then
49385 SetScrollPos(Handle, SB_CTL, Value, True);
49386 end;
49388 //[procedure TControl.SetSBMinMax]
49389 procedure TControl.SetSBMinMax(const Value: TPoint);
49390 begin
49391 GetSBMinMax;
49392 if (Handle <> 0) then
49393 SetScrollRange(Handle, SB_CTL, Value.X, Value.Y + SBPageSize - 1, True)
49394 else
49395 fSBMinMax := Value;
49396 end;
49398 //[procedure TControl.SBSetScrollInfo]
49399 function TControl.SBSetScrollInfo(const SI: TScrollInfo): Integer;
49400 begin
49401 Result := SetScrollInfo(Handle, SB_CTL, SI, True)
49402 end;
49404 //[procedure TControl.SBGetScrollInfo]
49405 function TControl.SBGetScrollInfo(var SI: TScrollInfo): Boolean;
49406 begin
49407 Result := Cardinal(GetScrollInfo(Handle, SB_CTL, SI)) <> 0;
49408 end;
49411 { -- OpenSaveDialog -- }
49414 //[function NewOpenSaveDialog]
49415 function NewOpenSaveDialog( const Title, StrtDir: String;
49416 Options: TOpenSaveOptions ): POpenSaveDialog;
49417 begin
49419 New( Result, Create );
49420 {+}{++}(*Result := POpenSaveDialog.Create;*){--}
49421 Result.FOptions := Options;
49422 if Options = [] then
49423 Result.FOptions := DefOpenSaveDlgOptions;
49424 Result.fOpenDialog := True;
49425 Result.FTitle := Title;
49426 Result.FInitialDir := StrtDir;
49427 end;
49428 //[END NewOpenSaveDialog]
49430 { TOpenSaveDialog }
49432 {$IFDEF ASM_VERSION}
49433 //[destructor TOpenSaveDialog.Destroy]
49434 destructor TOpenSaveDialog.Destroy;
49435 asm //cmd //opd
49436 PUSH EAX
49437 PUSH 0
49438 LEA EDX, [EAX].FFilter
49439 PUSH EDX
49440 LEA EDX, [EAX].FInitialDir
49441 PUSH EDX
49442 LEA EDX, [EAX].FDefExtension
49443 PUSH EDX
49444 LEA EDX, [EAX].FFileName
49445 PUSH EDX
49446 LEA EAX, [EAX].FTitle
49447 @@loo:
49448 CALL System.@LStrClr
49449 POP EAX
49450 TEST EAX, EAX
49451 JNZ @@loo
49452 POP EAX
49453 CALL TObj.Destroy
49454 end;
49455 {$ELSE ASM_VERSION} //Pascal
49456 destructor TOpenSaveDialog.Destroy;
49457 begin
49458 FFilter := '';
49459 FInitialDir := '';
49460 FDefExtension := '';
49461 FFileName := '';
49462 FTitle := '';
49463 {$IFDEF OpenSaveDialog_Extended}
49464 TemplateName := '';
49465 {$ENDIF}
49466 inherited;
49467 end;
49468 {$ENDIF ASM_VERSION}
49470 {$IFDEF ASM_VERSION}
49471 //[function TOpenSaveDialog.Execute]
49472 function TOpenSaveDialog.Execute: Boolean;
49474 PUSH EBX
49475 XCHG EBX, EAX
49477 XOR ECX, ECX
49478 {$IFDEF OpenSaveDialog_Extended}
49479 PUSH [EBX].TemplateName
49480 PUSH [EBX].HookProc
49481 {$ELSE}
49482 PUSH ECX // prepare lpTemplateName = nil
49483 PUSH ECX // prepare lpfnHook = nil
49484 {$ENDIF}
49485 PUSH EBX // prepare lCustData = @Self
49486 MOV EDX, [EBX].FDefExtension
49487 CALL EDX2PChar
49488 PUSH EDX // prepare lpstrDefExt = FDefExtension
49489 PUSH ECX // prepare nFileExtension, nFileOffset: Word = 0, 0
49490 // prepare flags:
49491 LEA EAX, [EBX].FOptions
49492 MOV EDX, Offset[@@OpenSaveFlags]
49493 {$IFDEF OpenSaveDialog_Extended}
49494 MOV CL, 14
49495 {$ELSE}
49496 MOV CL, 12
49497 {$ENDIF}
49498 CALL MakeFlags
49499 XOR ECX, ECX
49500 OR EAX, OFN_EXPLORER or OFN_LONGNAMES or OFN_ENABLESIZING
49501 PUSH EAX // push Flags
49502 PUSH [EBX].FTitle // prepare lpstrTitle
49503 PUSH [EBX].FInitialDir // prepare lpstrInitialDir
49504 PUSH ECX // prepare nMaxFileTitle = 0
49505 PUSH ECX // prepare lpstrFileTitle = nil
49506 TEST AH, 2 // MultiSelect?
49507 MOV EAX, 65520
49508 JNZ @@1
49509 MOV AX, MAX_PATH+2
49510 @@1: PUSH EAX // prepare nMaxFile
49511 CALL System.@GetMem
49512 POP ECX
49513 PUSH ECX
49514 PUSH EAX // prepare lpStrFile
49515 XOR EDX, EDX
49517 @@2: //MOV [EAX], DL // clear it initially {Vadim Petrov: it is necessary}
49518 //INC EAX
49519 //LOOP @@2
49521 MOV EDX, [EBX].fFileName // no, fill it initilly by FileName
49522 CALL EDX2PChar
49523 DEC ECX // added 5 october 2003 to prevent possible error if FileName too big
49524 CALL StrLCopy
49525 XOR EDX, EDX
49527 PUSH [EBX].FFilterIndex // prepare nFilterIndex
49528 PUSH EDX // prepare nMaxCustFilter
49529 PUSH EDX // prepare lpstrCustomFilter
49530 PUSH EDX // prepare lpstrFilter = nil
49531 MOV EAX, ESP
49532 OR EDX, [EBX].FFilter
49533 JZ @@5
49535 MOV ECX, offset[@@0]
49536 CALL System.@LStrCat3 // prepare lpStrFilter = FFilter + #0
49537 POP EAX
49538 PUSH EAX
49539 XOR EDX, EDX
49540 @@3: INC EAX // filter is not starting from ';' or '|'...
49541 CMP [EAX], DL
49542 JZ @@5
49543 CMP byte ptr [EAX], '|'
49544 JNZ @@3
49545 @@4: MOV [EAX], DL
49546 JMP @@3
49547 @@OpenSaveFlags:
49548 DD OFN_CREATEPROMPT, OFN_EXTENSIONDIFFERENT, OFN_FILEMUSTEXIST
49549 DD OFN_HIDEREADONLY, OFN_NOCHANGEDIR, OFN_NODEREFERENCELINKS
49550 DD OFN_ALLOWMULTISELECT, OFN_NONETWORKBUTTON, OFN_NOREADONLYRETURN
49551 DD OFN_OVERWRITEPROMPT, OFN_PATHMUSTEXIST, OFN_READONLY, OFN_NOVALIDATE
49552 {$IFDEF OpenSaveDialog_Extended}
49553 DD OFN_ENABLETEMPLATE, OFN_ENABLEHOOK
49554 {$ENDIF}
49556 DD -1, 1
49557 @@0: DB 0
49560 @@5:
49561 PUSH [hInstance] // prepare hInstance
49563 MOV ECX, [EBX].TControl.fWnd
49564 INC ECX
49565 LOOP @@6
49566 MOV ECX, [Applet]
49567 JECXZ @@6
49568 MOV ECX, [ECX].TControl.fHandle
49569 @@6: PUSH ECX // prepare hWndOwner
49570 PUSH 76 // prepare lStructSize
49572 PUSH ESP
49573 CMP [EBX].FOpenDialog, DL
49574 JZ @@7
49575 CALL GetOpenFileName
49576 JMP @@8
49577 @@7: CALL GetSaveFileName
49578 @@8:
49579 PUSH EAX
49580 XOR EDX, EDX
49581 TEST EAX, EAX
49582 JZ @@10
49584 MOV EAX, [ESP+4].TOpenFileName.nFilterIndex
49585 MOV [EBX].FFilterIndex, EAX
49587 MOV EAX, [ESP+4].TOpenFileName.lpstrFile
49588 MOV EDX, EAX
49589 XOR ECX, ECX
49591 TEST [EBX].FOptions, 1 shl OSAllowMultiSelect
49592 JZ @@10
49594 DEC EAX
49595 @@9: INC EAX
49596 CMP byte ptr [EAX], CL
49597 JNZ @@9
49598 CMP byte ptr [EAX+1], CL
49599 JZ @@10
49600 MOV byte ptr [EAX], 13
49601 JMP @@9
49603 @@10:
49604 LEA EAX, [EBX].FFileName
49605 CALL System.@LStrFromPChar
49606 MOV EAX, [ESP+4].TOpenFileName.lpstrFile
49607 CALL System.@FreeMem // v1.86 +AK
49609 LEA EAX, [ESP+4].TOpenFileName.lpstrFilter
49610 CALL System.@LStrClr
49612 POP EAX
49613 ADD ESP, 76
49614 POP EBX
49615 end;
49616 {$ELSE ASM_VERSION} //Pascal
49617 function TOpenSaveDialog.Execute: Boolean;
49618 const OpenSaveFlags: array[ TOpenSaveOption ] of Integer = (
49619 OFN_CREATEPROMPT,
49620 OFN_EXTENSIONDIFFERENT,
49621 OFN_FILEMUSTEXIST,
49622 OFN_HIDEREADONLY,
49623 OFN_NOCHANGEDIR,
49624 OFN_NODEREFERENCELINKS,
49625 OFN_ALLOWMULTISELECT,
49626 OFN_NONETWORKBUTTON,
49627 OFN_NOREADONLYRETURN,
49628 OFN_OVERWRITEPROMPT,
49629 OFN_PATHMUSTEXIST,
49630 OFN_READONLY,
49631 OFN_NOVALIDATE
49632 //{$IFDEF OpenSaveDialog_Extended}
49634 OFN_ENABLETEMPLATE,
49635 OFN_ENABLEHOOK
49636 //{$ENDIF}
49639 Ofn : TOpenFilename;
49640 Fltr : String;
49641 TempFilename : String;
49643 Function MakeFilter(s : string) : String;
49645 format of filter for API call is following:
49646 'text files'#0'*.txt'#0
49647 'bitmap files'#0'*.bmp'#0#0
49649 var Str: PChar;
49650 begin
49651 Result := s;
49652 if Result='' then
49653 exit;
49654 Result:=Result+#0; {Delphi string always end on #0 is this is #0#0}
49655 Str := PChar( Result );
49656 while Str^ <> #0 do
49657 begin
49658 if Str^ = '|' then
49659 Str^ := #0;
49660 Inc( Str );
49661 end;
49662 end;
49664 begin
49665 Fillchar( ofn, sizeof( ofn ), 0 );
49667 ofn.lStructSize:= 76; //to provide correct work in Win9x
49668 //sizeof(ofn); - by suggestion of Michael Morozov, 28-Nov-2001
49669 if fWnd <> 0 then
49670 ofn.hWndOwner := fWnd
49671 else
49672 if assigned(applet) then
49673 ofn.hwndOwner:=applet.Handle;
49675 ofn.hInstance:=HInstance;
49677 Fltr:=MakeFilter(FFilter);
49678 if Fltr <> '' then
49679 ofn.lpstrFilter:=pchar(Fltr);
49681 //ofn.lpstrCustomFilter:=nil;
49682 //ofn.nMaxCustFilter:=0;
49683 ofn.nFilterIndex:=FFilterIndex;
49685 if OSAllowMultiSelect in FOptions then
49686 ofn.nMaxFile:=High(word)-14 // by V.K. (exchanged condition)
49687 else
49688 ofn.nMaxFile:=MAX_PATH+2;
49690 TempFileName:=StringOfChar(#0,ofn.nMaxFile); {Vadim Petrov}
49691 ofn.lpstrFile:=StrLCopy(pchar(TempFileName), pchar(fFileName),
49692 Min(ofn.nMaxFile,Length(fFileName)));
49694 ofn.lpstrInitialDir:=Pointer(FInitialDir);
49695 ofn.lpstrTitle:=Pointer(FTitle);
49696 ofn.Flags := MakeFlags( @FOptions, OpenSaveFlags )
49697 or OFN_EXPLORER or OFN_LONGNAMES or OFN_ENABLESIZING;
49699 ofn.lpstrDefExt:=PChar(FDefExtension);
49700 ofn.lCustData:=integer(@self);
49701 {$IFDEF OpenSaveDialog_Extended}
49702 ofn.lpTemplateName := PChar( TemplateName );
49703 ofn.lpfnHook := HookProc;
49704 {$ELSE}
49705 ofn.lpTemplateName:=nil;
49706 ofn.lpfnHook:=nil;
49707 {$ENDIF}
49708 if fOpenDialog then
49709 result:=GetOpenFileName(ofn)
49710 else
49711 result:=GetSaveFileName(ofn);
49712 if result then begin
49713 fFilterIndex := ofn.nFilterIndex; // by Vadim
49714 if OSAllowMultiSelect in foptions then begin
49715 FFileName:=copy(TempFileName, 1, pos(#0#0, tempfilename)-1);
49716 while pos(#0, ffilename) > 0 do begin
49717 FFilename[pos(#0, ffilename)]:=#13;
49718 end;
49719 end else
49720 FFileName:=copy(tempFileName, 1, pos(#0, TempFilename)
49721 -1 // by X.Y.B.
49723 end else
49724 FFilename:='';
49725 end;
49726 {$ENDIF ASM_VERSION}
49728 { -- OpenDirDialog -- }
49731 //[function NewOpenDirDialog]
49732 function NewOpenDirDialog( const Title: String; Options: TOpenDirOptions ):
49733 POpenDirDialog;
49734 begin
49736 New( Result, Create );
49737 {+}{++}(*Result := POpenDirDialog.Create;*){--}
49738 Result.FOptions := [ odOnlySystemDirs ];
49739 if Options <> [] then
49740 Result.FOptions := Options;
49741 Result.FTitle := Title;
49742 end;
49743 //[END NewOpenDirDialog]
49745 { TOpenDirDialog }
49747 {$IFDEF ASM_VERSION}
49748 //[destructor TOpenDirDialog.Destroy]
49749 destructor TOpenDirDialog.Destroy;
49750 asm //cmd //opd
49751 PUSH EAX
49752 PUSH 0
49753 LEA EDX, [EAX].FTitle
49754 PUSH EDX
49755 LEA EDX, [EAX].FInitialPath
49756 PUSH EDX
49757 LEA EAX, [EAX].FStatusText
49758 @@loo: CALL System.@LStrClr
49759 POP EAX
49760 TEST EAX, EAX
49761 JNZ @@loo
49762 POP EAX
49763 CALL TObj.Destroy
49764 end;
49765 {$ELSE ASM_VERSION} //Pascal
49766 destructor TOpenDirDialog.Destroy;
49767 begin
49768 FTitle := '';
49769 FInitialPath := '';
49770 FStatusText := '';
49771 inherited;
49772 end;
49773 {$ENDIF ASM_VERSION}
49775 type
49776 {$IFNDEF _D2}
49777 (*IMalloc = interface(IUnknown)
49778 ['{00000002-0000-0000-C000-000000000046}']
49779 function Alloc(cb: Longint): Pointer; stdcall;
49780 function Realloc(pv: Pointer; cb: Longint): Pointer; stdcall;
49781 procedure Free(pv: Pointer); stdcall;
49782 function GetSize(pv: Pointer): Longint; stdcall;
49783 function DidAlloc(pv: Pointer): Integer; stdcall;
49784 procedure HeapMinimize; stdcall;
49785 end;*)
49786 {$ENDIF}
49788 PSHItemID = ^TSHItemID;
49789 TSHItemID = packed record
49790 cb: Word; { Size of the ID (including cb itself) }
49791 abID: array[0..0] of Byte; { The item ID (variable length) }
49792 end;
49794 PItemIDList = ^TItemIDList;
49795 TItemIDList = record
49796 mkid: TSHItemID;
49797 end;
49799 PBrowseInfo = ^TBrowseInfo;
49800 TBrowseInfo = record
49801 hwndOwner: HWND;
49802 pidlRoot: PItemIDList;
49803 pszDisplayName: PAnsiChar; { Return display name of item selected. }
49804 lpszTitle: PAnsiChar; { text to go in the banner over the tree. }
49805 ulFlags: UINT; { Flags that control the return stuff }
49806 lpfn: Pointer; //TFNBFFCallBack;
49807 lParam: LPARAM; { extra info that's passed back in callbacks }
49808 iImage: Integer; { output var: where to return the Image index. }
49809 end;
49811 //[API SHXXXXXXXXXX]
49812 function SHBrowseForFolder(var lpbi: TBrowseInfo): PItemIDList; stdcall;
49813 external 'shell32.dll' name 'SHBrowseForFolderA';
49814 function SHGetPathFromIDList(pidl: PItemIDList; pszPath: PChar): BOOL; stdcall;
49815 external shell32 name 'SHGetPathFromIDListA';
49817 function CoTaskMemAlloc(cb : DWORD) : pointer; stdcall; external 'ole32.dll'
49818 name 'CoTaskMemAlloc';
49820 procedure CoTaskMemFree(pv: Pointer); stdcall; external 'ole32.dll'
49821 name 'CoTaskMemFree';
49823 const
49824 BIF_RETURNONLYFSDIRS = $0001; { For finding a folder to start document searching }
49825 BIF_DONTGOBELOWDOMAIN = $0002; { For starting the Find Computer }
49826 BIF_STATUSTEXT = $0004;
49827 BIF_RETURNFSANCESTORS = $0008;
49828 BIF_EDITBOX = $0010;
49829 BIF_VALIDATE = $0020; { insist on valid result (or CANCEL) }
49830 BIF_BROWSEFORCOMPUTER = $1000; { Browsing for Computers. }
49831 BIF_BROWSEFORPRINTER = $2000; { Browsing for Printers }
49832 BIF_BROWSEINCLUDEFILES = $4000; { Browsing for Everything }
49834 BFFM_INITIALIZED = 1;
49835 BFFM_SELCHANGED = 2;
49837 BFFM_SETSTATUSTEXT = WM_USER + 100;
49838 BFFM_ENABLEOK = WM_USER + 101;
49839 BFFM_SETSELECTION = WM_USER + 102;
49842 {$IFDEF ASM_VERSION} // WndOwner
49843 //[function TOpenDirDialog.Execute]
49844 function TOpenDirDialog.Execute: Boolean;
49846 PUSH EBX
49847 XCHG EBX, EAX
49849 XOR ECX, ECX
49850 PUSH ECX // prepare iImage = 0
49851 PUSH EBX // prepare lParam = @Self
49852 PUSH [EBX].FCallBack // prepare lpfn = FCallBack
49853 LEA EAX, [EBX].FOptions
49854 MOV EDX, Offset[@@FlagsArray]
49855 MOV CL, 5
49856 CALL MakeFlags
49857 PUSH EAX // prepare ulFlags = Options
49858 PUSH [EBX].FTitle // prepare lpszTitle
49859 LEA EAX, [EBX].FBuf
49860 PUSH EAX // prepare pszDisplayName
49861 PUSH 0 // prepare pidlRoot
49862 MOV ECX, [EBX].fWnd
49863 INC ECX
49864 LOOP @@1
49865 MOV ECX, Applet
49866 JECXZ @@1
49867 MOV ECX, [ECX].TControl.fHandle
49868 @@1: PUSH ECX // prepare hwndOwner
49870 PUSH ESP
49871 CALL SHBrowseForFolder
49872 ADD ESP, 32
49873 TEST EAX, EAX
49874 JZ @@exit
49876 PUSH EAX
49878 LEA EDX, [EBX].FBuf
49879 PUSH EDX
49880 PUSH EAX
49881 CALL SHGetPathFromIDList
49883 CALL CoTaskMemFree
49885 MOV AL, 1
49886 JMP @@fin
49888 @@FlagsArray:
49889 DD BIF_BROWSEFORCOMPUTER, BIF_BROWSEFORPRINTER, BIF_DONTGOBELOWDOMAIN
49890 DD BIF_RETURNFSANCESTORS, BIF_RETURNONLYFSDIRS, BIF_STATUSTEXT, BIF_BROWSEINCLUDEFILES
49892 @@exit: XOR EAX, EAX
49893 @@fin:
49894 POP EBX
49895 end;
49896 {$ELSE ASM_VERSION} //Pascal
49897 function TOpenDirDialog.Execute: Boolean;
49898 const FlagsArray: array[ TOpenDirOption ] of Integer =
49899 ( BIF_BROWSEFORCOMPUTER, BIF_BROWSEFORPRINTER, BIF_DONTGOBELOWDOMAIN,
49900 BIF_RETURNFSANCESTORS, BIF_RETURNONLYFSDIRS, BIF_STATUSTEXT,
49901 BIF_BROWSEINCLUDEFILES );
49902 var BI : TBrowseInfo;
49903 Browse : PItemIdList;
49904 begin
49905 Result := False;
49906 if WndOwner <> 0 then
49907 BI.hwndOwner := WndOwner
49908 else
49909 if assigned( Applet ) then
49910 BI.hwndOwner := Applet.Handle
49911 else
49912 BI.hwndOwner := 0;
49913 BI.pidlRoot := nil;
49914 BI.pszDisplayName := @FBuf[ 0 ];
49915 BI.lpszTitle := PChar( Title );
49916 BI.ulFlags := MakeFlags( @FOptions, FlagsArray );
49917 BI.lpfn := FCallBack;
49918 BI.lParam := Integer( @Self );
49919 Browse := SHBrowseForFolder( BI );
49920 if Browse <> nil then
49921 begin
49922 SHGetPathFromIDList( Browse, @FBuf[ 0 ] );
49923 CoTaskMemFree( Browse );
49924 Result := True;
49925 end;
49926 end;
49927 {$ENDIF ASM_VERSION}
49929 //[function TOpenDirDialog.GetInitialPath]
49930 function TOpenDirDialog.GetInitialPath: String;
49931 begin
49932 Result := IncludeTrailingPathDelimiter( fInitialPath );
49933 end;
49935 //[function TOpenDirDialog.GetPath]
49936 function TOpenDirDialog.GetPath: String;
49937 begin
49938 Result := FBuf;
49939 end;
49941 //[FUNCTION OpenDirSelChangeCallBack]
49942 {$IFDEF ASM_VERSION}
49943 function OpenDirSelChangeCallBack( Wnd: HWnd; Msg: DWORD; lParam, lpData: LParam ):
49944 Integer; stdcall;
49946 MOV EAX, [lpData]
49947 MOV ECX, [EAX].TOpenDirDialog.FOnSelChanged.TMethod.Code
49948 JECXZ @@exit
49950 LEA EDX, [EAX].TOpenDirDialog.FBuf
49951 PUSH EDX
49952 PUSH [lParam]
49953 CALL SHGetPathFromIDList
49955 //EnableOK := 0;
49956 //Self_.FOnSelChanged( Self_, Self_.FBuf, EnableOK, Self_.FStatusText );
49958 MOV EDX, [lpData]
49959 LEA ECX, [EDX].TOpenDirDialog.FBuf
49960 PUSH 0
49961 PUSH ESP
49962 LEA EAX, [EDX].TOpenDirDialog.FStatusText
49963 PUSH EAX
49964 MOV EAX, [EDX].TOpenDirDialog.FOnSelChanged.TMethod.Data
49965 CALL dword ptr [EDX].TOpenDirDialog.FOnSelChanged.TMethod.Code
49966 POP ECX
49967 JECXZ @@1
49969 INC ECX
49970 PUSH ECX
49971 PUSH 0
49972 PUSH BFFM_ENABLEOK
49973 PUSH [Wnd]
49974 CALL SendMessage
49975 @@1:
49976 MOV EDX, [lpData]
49977 MOV ECX, [EDX].TOpenDirDialog.FStatusText
49978 JECXZ @@exit
49980 PUSH ECX
49981 PUSH 0
49982 PUSH BFFM_SETSTATUSTEXT
49983 PUSH [Wnd]
49984 CALL SendMessage
49986 @@exit: XOR EAX, EAX
49987 end;
49988 {$ELSE ASM_VERSION} //Pascal
49989 function OpenDirSelChangeCallBack( Wnd: HWnd; Msg: DWORD; lParam, lpData: LParam ):
49990 Integer; stdcall;
49991 var _Self_: POpenDirDialog;
49992 EnableOK: Integer;
49993 begin
49994 _Self_ := Pointer( lpData );
49995 if assigned( _Self_.FOnSelChanged ) then
49996 begin
49997 SHGetPathFromIDList( PItemIDList( lParam ), @ _Self_.FBuf[ 0 ] );
49998 EnableOK := 0;
49999 _Self_.FOnSelChanged( _Self_, _Self_.FBuf, EnableOK, _Self_.FStatusText );
50000 if EnableOK <> 0 then
50001 SendMessage( Wnd, BFFM_ENABLEOK, 0, EnableOK + 1 );
50002 if _Self_.FStatusText <> '' then
50003 SendMessage( Wnd, BFFM_SETSTATUSTEXT, 0, Integer( PChar( _Self_.FStatusText ) ) );
50004 end;
50005 Result := 0;
50006 end;
50007 {$ENDIF ASM_VERSION}
50008 //[END OpenDirSelChangeCallBack]
50010 //[FUNCTION OpenDirCallBack]
50011 {$IFDEF ASM_VERSION}
50012 function OpenDirCallBack( Wnd: HWnd; Msg: DWORD; lParam, lpData: LParam ): Integer;
50013 stdcall;
50015 MOV EAX, [Wnd]
50016 MOV EDX, [lpData]
50017 MOV ECX, [Msg]
50018 LOOP @@chk_sel_chg
50019 // Msg = 1 -> BFFM_Initialized
50021 MOV ECX, [EDX].TOpenDirDialog.FCenterProc
50022 JECXZ @@1
50023 PUSH EDX
50024 CALL ECX
50025 POP EDX
50026 @@1: MOV ECX, [EDX].TOpenDirDialog.FInitialPath
50027 JECXZ @@exit
50028 PUSH ECX
50029 PUSH 1
50030 PUSH BFFM_SETSELECTION
50031 PUSH [Wnd]
50032 CALL SendMessage
50033 JMP @@exit
50035 @@chk_sel_chg:
50036 LOOP @@exit
50037 // Msg = 2 -> BFFM_SelChanged
50039 MOV ECX, [EDX].TOpenDirDialog.FDoSelChanged
50040 JECXZ @@exit
50041 POP EBP
50042 JMP ECX
50044 @@exit: XOR EAX, EAX
50045 end;
50046 {$ELSE ASM_VERSION} //Pascal
50047 function OpenDirCallBack( Wnd: HWnd; Msg: DWORD; lParam, lpData: LParam ): Integer;
50048 stdcall;
50049 var Self_ : POpenDirDialog;
50050 begin
50051 Self_ := Pointer( lpData );
50052 if Msg = BFFM_INITIALIZED then
50053 begin
50054 if assigned( Self_.FCenterProc ) then
50055 Self_.FCenterProc( Wnd );
50056 if Self_.FInitialPath <> '' then
50057 SendMessage( Wnd, BFFM_SETSELECTION, 1, Integer( PChar( Self_.FInitialPath ) ) );
50059 else
50060 if Msg = BFFM_SELCHANGED then
50061 begin
50062 if assigned( Self_.FDoSelChanged ) then
50063 Self_.FDoSelChanged( Wnd, Msg, lParam, lpData );
50064 end;
50065 Result := 0;
50066 end;
50067 {$ENDIF ASM_VERSION}
50068 //[END OpenDirCallBack]
50070 //[PROCEDURE OpenDirDlgCenter]
50071 {$IFDEF ASM_VERSION}
50072 procedure OpenDirDlgCenter( Wnd: HWnd );
50074 PUSH EBX
50075 MOV EBX, EAX
50077 ADD ESP, -16
50078 PUSH ESP
50079 PUSH EAX
50080 CALL GetWindowRect
50081 POP EDX // EDX = Left
50082 POP ECX // ECX = Top
50083 POP EAX // EAX = Right
50084 SUB EAX, EDX // EAX = W
50085 POP EDX // EDX = Bottom
50086 SUB EDX, ECX // EDX = H
50087 XOR ECX, ECX
50088 INC ECX
50089 PUSH ECX // prepare True
50090 PUSH EDX // prepare H
50091 PUSH EAX // prepare W
50093 INC ECX
50094 @@1:
50095 PUSH ECX
50097 DEC ECX
50098 PUSH ECX
50099 CALL GetSystemMetrics
50101 POP ECX
50102 SUB EAX, [ESP+4]
50103 SAR EAX, 1
50104 PUSH EAX
50106 LOOP @@1
50109 PUSH SM_CYSCREEN
50110 CALL GetSystemMetrics
50111 SUB EAX, [ESP+4]
50112 SAR EAX, 1
50113 PUSH EAX
50115 PUSH SM_CXSCREEN
50116 CALL GetSystemMetrics
50117 SUB EAX, [ESP+4]
50118 SAR EAX, 1
50119 PUSH EAX
50122 PUSH EBX
50123 CALL MoveWindow
50124 POP EBX
50125 end;
50126 {$ELSE ASM_VERSION} //Pascal
50127 procedure OpenDirDlgCenter( Wnd: HWnd );
50128 var R: TRect;
50129 W, H: Integer;
50130 begin
50131 GetWindowRect( Wnd, R );
50132 W := R.Right - R.Left;
50133 H := R.Bottom - R.Top;
50134 R.Left := (GetSystemMetrics( SM_CXSCREEN ) - W) div 2;
50135 R.Top := (GetSystemMetrics( SM_CYSCREEN ) - H) div 2;
50136 MoveWindow( Wnd, R.Left, R.Top, W, H, True );
50137 end;
50138 {$ENDIF ASM_VERSION}
50139 //[END OpenDirDlgCenter]
50141 {$IFDEF ASM_VERSION}
50142 //[procedure TOpenDirDialog.SetCenterOnScreen]
50143 procedure TOpenDirDialog.SetCenterOnScreen(const Value: Boolean);
50145 MOV [EAX].FCenterOnScreen, DL
50146 MOVZX ECX, DL
50147 JECXZ @@1
50148 MOV ECX, Offset[OpenDirDlgCenter]
50149 @@1: MOV [EAX].FCenterProc, ECX
50150 end;
50151 {$ELSE ASM_VERSION} //Pascal
50152 procedure TOpenDirDialog.SetCenterOnScreen(const Value: Boolean);
50153 var P: procedure( Wnd: HWnd );
50154 begin
50155 FCenterOnScreen := Value;
50156 P := nil;
50157 if Value then
50158 P := @OpenDirDlgCenter;
50159 FCenterProc := P;
50160 end;
50161 {$ENDIF ASM_VERSION}
50163 //[procedure TOpenDirDialog.SetInitialPath]
50164 procedure TOpenDirDialog.SetInitialPath(const Value: String);
50165 begin
50166 FCallBack := @OpenDirCallBack;
50167 FInitialPath := ExcludeTrailingPathDelimiter( Value );
50168 end;
50170 //[procedure TOpenDirDialog.SetOnSelChanged]
50171 procedure TOpenDirDialog.SetOnSelChanged(const Value: TOnODSelChange);
50172 begin
50173 FOnSelChanged := Value;
50174 FCallBack := @OpenDirCallBack;
50175 FDoSelChanged := @OpenDirSelChangeCallBack;
50176 end;
50179 type
50180 PByteArray =^TByteArray;
50181 TByteArray = array[Word]of Byte;
50183 //[API CreateMappedBitmap]
50184 function CreateMappedBitmap(Instance: THandle; Bitmap: Integer;
50185 Flags: UINT; ColorMap: PColorMap; NumMaps: Integer): HBitmap; stdcall;
50186 external cctrl name 'CreateMappedBitmap';
50188 //[function CreateMappedBitmapEx]
50189 function CreateMappedBitmapEx(Instance: THandle; BmpRsrcName: PChar; Flags:
50190 Cardinal; ColorMap: PColorMap; NumMaps: Integer): HBitmap;
50191 var bi: TBITMAPINFO;
50192 DC, tmcl: Cardinal;
50193 Bits: PByteArray;
50194 i, j, k, CO, bps: Integer;
50195 tm: array [1..4] of byte absolute tmcl;
50196 bm: Windows.TBITMAP;
50197 CM: PColorMap;
50198 DW: HWnd;
50199 begin
50200 Result := LoadBitmap( Instance, BmpRsrcName );
50201 if Result = 0 then
50202 begin
50203 {$IFDEF DEBUG}
50204 ShowMessage( 'Can not load bitmap ' + BmpRsrcName + ', error ' +
50205 Int2Str( GetLastError ) + ': ' + SysErrorMessage( GetLastError ) );
50206 {$ENDIF}
50207 Exit;
50208 end;
50209 DW := GetDesktopWindow;
50210 DC := GetDC(DW);
50211 FillChar( bm, SizeOf(bm), 0 );
50212 GetObject( Result, SizeOf( bm ), @bm );
50214 FillChar( bi, SizeOf( bi ), 0 );
50215 bi.bmiHeader.biSize := SizeOf( bi.bmiHeader );
50216 bi.bmiHeader.biWidth := bm.bmWidth;
50217 bi.bmiHeader.biHeight := -bm.bmHeight;
50218 bi.bmiHeader.biPlanes := 1;
50219 bi.bmiHeader.biBitCount := 24;
50220 // BitCout - always 24 for easy algorythm
50221 bi.bmiHeader.biCompression:=BI_RGB;
50222 bps := CalcScanLineSize( @bi.bmiHeader );
50224 GetMem( Bits, bps * bm.bmHeight );
50225 GetDIBits( DC, Result, 0, bm.bmHeight, @Bits[0], bi, DIB_RGB_COLORS );
50226 DeleteObject( Result );
50228 for i := 0 to bm.bmHeight - 1 do begin
50229 for j := 0 to bm.bmWidth - 1 do begin
50230 CO := bps * i + 3 * j;
50231 for k := 0 to NumMaps - 1 do begin
50232 CM := Pointer( Integer( ColorMap ) + SizeOf( TColorMap ) * k );
50233 if RGB( Bits[CO+2], Bits[CO+1], Bits[CO] ) = CM.cFrom then
50234 begin
50235 tmcl := CM.cTo;
50236 tm[4]:=tm[1];
50237 tm[1]:=tm[3];
50238 tm[3]:=tm[4];
50239 Move( tmcl, Bits[CO], 3);
50240 end;
50241 end;
50242 end;
50243 end;
50244 Result := CreateDIBitmap( DC, bi.bmiHeader, CBM_INIT, @Bits[0], bi,
50245 DIB_RGB_COLORS );
50246 ReleaseDC( DW, DC );
50247 FreeMem( Bits );
50248 end;
50251 //[function LoadMappedBitmap]
50252 function LoadMappedBitmap( hInst: THandle; BmpResID: Integer; const Map: array of TColor )
50253 : HBitmap;
50254 var Map2Pass: Pointer;
50255 begin
50256 Map2Pass := nil;
50257 if High( Map ) > 0 then
50258 Map2Pass := PColorMap( @Map[ 0 ] );
50259 Result := CreateMappedBitmap( hInst, BmpResID, 0, Map2Pass, (High( Map ) + 1) div 2 );
50260 end;
50262 //[function LoadMappedBitmapEx]
50263 function LoadMappedBitmapEx( MasterObj: PObj; hInst: THandle; BmpResName: PChar; const Map: array of TColor )
50264 : HBitmap;
50265 var Map2Pass: Pointer;
50266 begin
50267 Map2Pass := nil;
50268 if High( Map ) > 0 then
50269 Map2Pass := PColorMap( @Map[ 0 ] );
50270 Result := CreateMappedBitmapEx( hInst, BmpResName, 0, Map2Pass, (High( Map ) + 1) div 2 );
50271 if MasterObj <> nil then
50272 MasterObj.Add2AutoFreeEx( TObjectMethod( MakeMethod( Pointer( Result ), @ FreeBmp ) ) );
50273 end;
50275 { -- Toolbar -- }
50277 {$IFDEF ASM_noVERSION} // width
50278 //[procedure TControl.TBAddBitmap]
50279 procedure TControl.TBAddBitmap(Bitmap: HBitmap);
50280 const szBI = sizeof(TBitmapInfo);
50282 TEST EDX, EDX
50283 JZ @@exit
50284 JGE @@1
50285 CMP EDX, -6
50286 JL @@1
50288 NEG EDX
50289 DEC EDX
50290 PUSH EDX
50291 PUSH -1
50292 XOR EDX, EDX
50293 JMP @@2
50295 @@1: PUSH EDX // AB.hInst = Bitmap
50296 PUSH 0 // AB.nID = 0
50298 PUSH EAX // > @Self
50299 ADD ESP, -szBI
50300 PUSH ESP
50301 PUSH szBI
50302 PUSH EDX
50303 CALL GetObject
50304 TEST EAX, EAX
50305 JG @@11
50307 ADD ESP, szBI
50308 JMP @@exit
50310 @@11: MOV EAX, [ESP].TBitmapInfo.bmiHeader.biWidth
50311 MOV ECX, [ESP].TBitmapInfo.bmiHeader.biHeight
50312 TEST ECX, ECX
50313 JGE @@12
50314 NEG ECX
50315 @@12: ADD ESP, szBI
50316 CDQ // EDX = 0
50317 DIV ECX // EAX = N
50318 XCHG EAX, [ESP] // > N
50319 PUSH EAX // > @Self
50321 MOV EDX, ECX
50322 SHL EDX, 16
50323 OR ECX, EDX
50325 PUSH EDX
50326 PUSH EDX
50327 PUSH TB_AUTOSIZE
50328 PUSH EAX
50330 PUSH ECX
50331 PUSH EDX
50332 PUSH TB_SETBITMAPSIZE
50333 PUSH EAX
50334 CALL Perform
50335 CALL Perform
50336 POP EAX
50337 POP EDX
50339 @@2: PUSH ESP
50340 PUSH EDX
50341 PUSH TB_ADDBITMAP
50342 PUSH EAX
50343 CALL Perform
50344 POP ECX
50345 POP ECX
50346 @@exit:
50347 end;
50348 {$ELSE ASM_VERSION} //Pascal
50349 procedure TControl.TBAddBitmap(Bitmap: HBitmap);
50350 const NstdBitmaps: array[ 0..5 ] of DWORD = ( 15, 15, 0, 0, 13, 13 );
50351 var BI: TBitmapInfo;
50352 AB: TTBAddBitmap;
50353 N, W: Integer;
50354 begin
50355 if Bitmap = 0 then Exit;
50356 if (Integer( Bitmap ) >= -10) and (Integer( Bitmap ) <= -1) then
50357 begin
50358 AB.hInst := THandle(-1);
50359 AB.nID := -Integer(Bitmap) - 1;
50360 N := 0; //NstdBitmaps[ AB.nID ]; // (this value is ignored)
50362 else
50363 if GetObject( Bitmap, sizeof( TBitmapInfo ), @BI ) > 0 then
50364 begin
50365 AB.hInst := 0;
50366 AB.nID := Bitmap;
50367 W := fTBBtnImgWidth;
50368 if W = 0 then
50369 W := Abs( BI.bmiHeader.biHeight );
50370 N := BI.bmiHeader.biWidth div W;
50371 Perform( TB_SETBITMAPSIZE, 0, MAKELONG( W, Abs(BI.bmiHeader.biHeight )) );
50372 Perform( TB_AUTOSIZE, 0, 0 );
50374 else Exit;
50375 Perform( TB_ADDBITMAP, N, Integer( @AB ) );
50376 end;
50377 {$ENDIF ASM_VERSION}
50379 var ToolbarsIDcmd: Integer = 100;
50380 {$IFDEF ASM_VERSION}
50381 //[function TControl.TBAddInsButtons]
50382 function TControl.TBAddInsButtons(Idx: Integer; const Buttons: array of PChar;
50383 const BtnImgIdxArray: array of Integer): Integer; stdcall;
50385 { [EBP+$8] = @Self
50386 [EBP+$C] = Idx
50387 [EBP+$10] = Buttons
50388 [EBP+$14] = High(Butons)
50389 [EBP+$18] = BtnImgIdxArray
50390 [EBP+$1C] = High(BtnImgIdxArray)
50392 PUSH EBX
50393 PUSH ESI
50394 PUSH EDI
50395 OR EBX, -1
50396 MOV EAX, 20
50397 MOV ECX, [EBP+$14]
50398 CMP ECX, EBX
50399 JLE @@fin
50400 INC ECX
50401 MUL ECX
50402 CALL System.@GetMem
50403 PUSH EAX // save AB to FreeMem after
50404 MOV EDX, EBX
50405 DEC EDX // nBmp := -2
50407 MOV ECX, [EBP+$14]
50408 INC ECX
50409 JZ @@exit
50411 MOV ECX, [EBP+$1C]
50412 INC ECX
50413 JZ @@1
50414 MOV ECX, [BtnImgIdxArray]
50415 MOV EDX, [ECX]
50416 DEC EDX // nBmp := BtnImgIdxArray[ 0 ] - 1
50417 @@1: MOV ECX, [EBP+$14]
50418 INC ECX
50419 MOV ESI, [Buttons]
50420 MOV EDI, EAX // EDI = PAB
50421 PUSH 0 // N:=0 in [EBP-$14]
50422 // -- impossible?-- JZ @@break
50423 @@loop:
50424 LODSD
50425 TEST EAX, EAX
50426 JZ @@break
50427 //CMP byte ptr [EAX], 0
50428 //JZ @@break
50429 PUSH ECX
50431 CMP word ptr [EAX], '-'
50432 JNE @@2
50434 OR EAX, -1
50435 STOSD
50436 //INC EAX //=0
50437 MOV EAX, [ToolbarsIDcmd]
50438 TEST EBX, EBX
50439 {$IFDEF USE_CMOV}
50440 CMOVL EBX, EAX
50441 {$ELSE}
50442 JGE @@b0
50443 MOV EBX, EAX
50444 @@b0: {$ENDIF}
50446 //INC [ToolbarsIDcmd]
50447 STOSD
50448 XOR EAX, EAX
50449 INC AH // TBSTYLE_SEP = 1
50450 STOSD
50451 DEC AH
50452 STOSD
50453 DEC EAX
50454 JMP @@3
50456 DD -1, 1
50457 @@0: DB 0
50459 @@2:
50460 INC EDX // Inc( nBmp )
50461 PUSH EAX
50463 MOV EAX, [EBP+$1C]
50464 MOV ECX, [EBP-$14]
50465 CMP EAX, ECX
50466 MOV EAX, EDX
50467 JL @@21
50468 MOV EAX, [BtnImgIdxArray]
50469 MOV EAX, [EAX+ECX*4]
50470 @@21: STOSD
50472 TEST EDX, EDX
50473 JGE @@2a
50474 DEC EDX
50475 @@2a:
50477 MOV EAX, [ToolbarsIDcmd]
50478 //INC [ToolbarsIDcmd]
50479 STOSD
50480 TEST EBX, EBX
50481 {$IFDEF USE_CMOV}
50482 CMOVL EBX, EAX
50483 {$ELSE}
50484 JGE @@210
50485 MOV EBX, EAX
50486 @@210: {$ENDIF}
50488 POP ECX
50489 MOV AX, $1004 // AL=fsState=_ENABLED, AH=fsStyle=_AUTOSIZE
50490 CMP byte ptr [ECX], '^'
50491 JNE @@22
50492 MOV AH, TBSTYLE_DROPDOWN or TBSTYLE_AUTOSIZE
50493 INC ECX
50494 @@22: CMP byte ptr [ECX], '-'
50495 JZ @@23
50496 CMP byte ptr [ECX], '+'
50497 JNZ @@24
50498 MOV AL, TBSTATE_ENABLED or TBSTATE_CHECKED
50499 @@23: INC ECX
50500 OR AH, TBSTYLE_CHECK
50501 CMP byte ptr [ECX], '!'
50502 JNZ @@24
50503 OR AH, TBSTYLE_GROUP
50504 INC ECX
50505 @@24: STOSD
50506 MOV EAX, [EBP+8]
50507 STOSD
50508 OR EAX, -1
50509 CMP word ptr [ECX], ' '
50510 JZ @@3
50511 CMP byte ptr [ECX], 0
50512 JZ @@3
50514 PUSH EDX
50515 PUSH 0
50516 MOV EDX, ECX
50517 MOV EAX, ESP
50518 CALL System.@LStrFromPChar
50519 MOV EAX, ESP
50520 MOV EDX, offset[@@0]
50521 CALL System.@LStrCat
50522 PUSH dword ptr [ESP]
50523 PUSH 0
50524 PUSH TB_ADDSTRING
50525 PUSH dword ptr [EBP+8]
50526 CALL Perform
50527 STOSD
50529 CALL RemoveStr
50530 POP EDX
50531 JMP @@30
50533 @@3: STOSD
50534 @@30: INC dword ptr [EBP-$14]
50535 INC [ToolbarsIDcmd]
50536 POP ECX
50537 DEC ECX
50538 JNZ @@loop
50539 @@break:
50540 POP ECX
50541 JECXZ @@exit
50542 PUSH dword ptr [ESP]
50543 MOV EAX, [Idx]
50544 TEST EAX, EAX
50545 JGE @@31
50547 PUSH ECX
50548 PUSH TB_ADDBUTTONS
50549 JMP @@32
50550 @@31:
50551 PUSH EAX
50552 PUSH TB_INSERTBUTTON
50553 @@32:
50554 PUSH dword ptr [EBP+8]
50555 CALL Perform
50556 @@exit:
50557 POP EAX
50558 //TEST EAX, EAX
50559 //JZ @@fin
50560 CALL System.@FreeMem
50562 @@fin:
50563 POP EDI
50564 POP ESI
50565 XCHG EAX, EBX
50566 POP EBX
50567 end;
50568 {$ELSE ASM_VERSION} //Pascal
50569 function TControl.TBAddInsButtons(Idx: Integer; const Buttons: array of PChar;
50570 const BtnImgIdxArray: array of Integer): Integer; stdcall;
50572 function AddInsButtons: Integer;
50573 type TTBBtnArray = array[ 0..100000 ] of TTBButton;
50574 PTBBtnArray = ^TTBBtnArray;
50575 var AB: PTBBtnArray;
50576 I, N, nBmp: Integer;
50577 PAB: PTBButton;
50578 Str: PChar;
50579 begin
50580 Result := -1;
50581 AB := nil;
50582 if High( Buttons ) >= 0 then
50583 GetMem( AB, Sizeof( TTBButton ) * (High(Buttons) + 1) );
50584 N := 0;
50585 PAB := @AB[ 0 ];
50586 nBmp := -2;
50587 if High(BtnImgIdxArray) >= 0 then
50588 nBmp := BtnImgIdxArray[ 0 ] - 1;
50589 for I:= 0 to High( Buttons ) do
50590 begin
50591 if Buttons[ I ] = nil then break;
50593 {if High( BtnImgIdxArray ) >= 0 then
50594 if I > High( BtnImgIdxArray ) then
50595 nBmp := -3;}
50597 if Buttons[ I ] = {$IFDEF F_P}''+{$ENDIF} '-' then
50598 begin
50599 PAB.iBitmap := -1;
50600 //PAB.idCommand := 0;
50601 PAB.fsState := 0;
50602 PAB.fsStyle := TBSTYLE_SEP;
50603 PAB.iString := -1;
50605 else
50606 begin
50607 Str := Buttons[ I ];
50608 Inc( nBmp );
50609 PAB.iBitmap := nBmp;
50610 if nBmp < 0 then
50611 Dec( nBmp );
50612 if High( BtnImgIdxArray ) >= N then
50613 PAB.iBitmap := BtnImgIdxArray[ N ];
50614 {PAB.idCommand := ToolbarsIDcmd;
50615 if Result < 0 then Result := PAB.idCommand;
50616 Inc( ToolbarsIDcmd );}
50617 PAB.fsState := TBSTATE_ENABLED;
50618 PAB.fsStyle := TBSTYLE_BUTTON or TBSTYLE_AUTOSIZE;
50619 if Str^ = '^' then
50620 begin
50621 PAB.fsStyle := TBSTYLE_DROPDOWN or TBSTYLE_AUTOSIZE;
50622 Inc( Str );
50623 end;
50624 if Str^ in [ '-', '+' ] then
50625 begin
50626 PAB.fsStyle := PAB.fsStyle or TBSTYLE_CHECK;
50627 if Str^ = '+' then
50628 PAB.fsState := PAB.fsState or TBSTATE_CHECKED;
50629 Inc( Str );
50630 if Str^ = '!' then
50631 begin
50632 PAB.fsStyle := PAB.fsStyle or TBSTYLE_GROUP;
50633 Inc( Str );
50634 end;
50635 end;
50636 if (Str = {$IFDEF F_P}''+{$ENDIF} ' ') or (Str^ = #0) then
50637 PAB.iString := -1
50638 //Perform( TB_ADDSTRING, 0, Integer( PChar( '' + #0 ) ) )
50639 // an experiment: is it possible to remove space right to image
50640 // without setting tboTextBottom option (non compatible with FixFlatXP)
50641 // answer: seems not possible.
50642 else
50643 PAB.iString :=
50644 Perform( TB_ADDSTRING, 0, Integer( PChar( '' + Str + #0 ) ) );
50645 end;
50647 PAB.idCommand := ToolbarsIDcmd;
50648 if Result < 0 then Result := PAB.idCommand;
50649 Inc( ToolbarsIDcmd );
50651 PAB.dwData := Integer( @Self );
50652 Inc( N );
50653 Inc( PAB );
50654 end;
50655 if N > 0 then
50656 begin
50657 if Idx < 0 then
50658 Perform( TB_ADDBUTTONS, N, Integer( @AB[ 0 ] ) )
50659 else
50660 Perform( TB_INSERTBUTTON, Idx, Integer( @AB[ 0 ] ) );
50661 end;
50662 if AB <> nil then
50663 FreeMem( AB );
50664 end;
50665 begin
50666 if High( Buttons ) < 0 then
50667 Result := -1
50668 else
50669 Result := AddInsButtons;
50670 end;
50671 {$ENDIF ASM_VERSION}
50673 {$IFDEF ASM_VERSION}
50674 //[function TControl.TBAddButtons]
50675 function TControl.TBAddButtons(const Buttons: array of PChar;
50676 const BtnImgIdxArray: array of Integer): Integer;
50678 PUSH dword ptr [EBP+8]
50679 PUSH dword ptr [EBP+12]
50680 PUSH ECX
50681 PUSH EDX
50682 PUSH -1
50683 PUSH EAX
50684 CALL TBAddInsButtons
50685 end;
50686 {$ELSE ASM_VERSION} //Pascal
50687 function TControl.TBAddButtons(const Buttons: array of PChar;
50688 const BtnImgIdxArray: array of Integer): Integer;
50689 begin
50690 Result := TBAddInsButtons( -1, Buttons, BtnImgIdxArray );
50691 end;
50692 {$ENDIF ASM_VERSION}
50695 //[function TControl.TBInsertButtons]
50696 function TControl.TBInsertButtons(BeforeIdx: Integer;
50697 Buttons: array of PChar; BtnImgIdxArray: array of Integer): Integer;
50698 var I, J, K: Integer;
50699 begin
50700 J := -1;
50701 Result := -1;
50702 for I := 0 to High( Buttons ) do
50703 begin
50704 if I <= High( BtnImgIdxArray ) then
50705 J := BtnImgIdxArray[ I ]
50706 else
50707 if J >= 0 then Inc( J );
50708 K := TBAddInsButtons( BeforeIdx, [ Buttons[ I ], '' ], [ J ] );
50709 if Result < 0 then Result := K;
50710 end;
50711 end;
50713 //[function GetTBBtnGoodID]
50714 function GetTBBtnGoodID( Toolbar: PControl; BtnIDorIdx: Integer ): Integer;
50715 // change by Alexander Pravdin (to fix toolbar with separator first):
50716 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
50717 var Btn1st, i: Integer; btn: TTBButton;
50718 begin
50719 Result := BtnIDorIdx;
50720 Btn1st := 0;
50721 for i := 0 to Toolbar.TBButtonCount - 1 do begin
50722 Toolbar.Perform( TB_GETBUTTON, i, Integer( @btn ) );
50723 if btn.fsStyle <> TBSTYLE_SEP then begin
50724 Btn1st := i;
50725 Break;
50726 end;
50727 end;
50728 if Result < Toolbar.TBIndex2Item( Btn1st ) then
50729 Result := Toolbar.TBIndex2Item( Result );
50730 end;
50732 type
50733 TTBButtonEvent = packed Record
50734 BtnID: DWORD;
50735 Event: TOnToolbarButtonClick;
50736 end;
50737 PTBButtonEvent = ^TTBButtonEvent;
50739 //[procedure TControl.TBFreeTBevents]
50740 procedure TControl.TBFreeTBevents;
50741 begin
50742 fTBevents.Release;
50743 end;
50745 //[function WndProcToolbarButtonsClicks]
50746 function WndProcToolbarButtonsClicks( TB: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
50747 var Notify: PTBNotify;
50748 I: Integer;
50749 Event: PTBButtonEvent;
50750 begin
50751 Result := FALSE;
50752 if Msg.message = WM_NOTIFY then
50753 begin
50754 Notify := Pointer( Msg.lParam );
50755 if Notify.hdr.code = NM_CLICK then
50756 begin
50757 for I := TB.fTBevents.fCount-1 downto 0 do
50758 begin
50759 Event := TB.fTBevents.fItems[ I ];
50760 if Integer( Event.BtnID ) = Notify.iItem then
50761 begin
50762 if Assigned( Event.Event ) then
50763 begin
50764 TB.RefInc;
50765 Rslt := DefWindowProc( Msg.hwnd, Msg.message, Msg.wParam, Msg.lParam );
50766 Event.Event( TB, Event.BtnID );
50767 //Rslt := TB.CallDefWndProc( Msg );
50768 TB.RefDec;
50769 Result := TRUE;
50770 Exit;
50771 end;
50772 break;
50773 end;
50774 end;
50775 end;
50776 end;
50777 end;
50779 //[procedure TControl.TBAssignEvents]
50780 procedure TControl.TBAssignEvents(BtnID: Integer;
50781 Events: array of TOnToolbarButtonClick);
50782 var I: Integer;
50783 EventRec: PTBButtonEvent;
50784 begin
50785 if fTBevents = nil then
50786 begin
50787 fTBevents := NewList;
50788 Add2AutoFreeEx( TBFreeTBevents );
50789 AttachProc( WndProcToolbarButtonsClicks );
50790 end;
50791 BtnID := GetTBBtnGoodID( @Self, BtnID );
50792 for I := 0 to High( Events ) do
50793 begin
50794 GetMem( EventRec, Sizeof( TTBButtonEvent ) );
50795 fTBevents.Add( EventRec );
50796 EventRec.Event := Events[ I ];
50797 EventRec.BtnID := BtnID;
50798 Inc( BtnID );
50799 end;
50800 end;
50802 //[procedure TControl.TBResetImgIdx]
50803 procedure TControl.TBResetImgIdx( BtnID, BtnCount: Integer );
50804 begin
50805 while BtnCount > 0 do
50806 begin
50807 TBButtonImage[ BtnID ] := -2;
50808 Inc( BtnID );
50809 Dec( BtnCount );
50810 end;
50811 end;
50814 //[function TControl.TBGetButtonVisible]
50815 function TControl.TBGetButtonVisible(BtnID: Integer): Boolean;
50816 begin
50817 Result := Perform( TB_ISBUTTONHIDDEN, GetTBBtnGoodID( @ Self, BtnID ), 0 ) = 0;
50818 end;
50821 //[function TControl.TBItem2Index]
50822 function TControl.TBItem2Index(BtnID: Integer): Integer;
50823 begin
50824 Result := Perform( TB_COMMANDTOINDEX, BtnID, 0 );
50825 end;
50828 //[procedure TControl.TBSetButtonVisible]
50829 procedure TControl.TBSetButtonVisible(BtnID: Integer;
50830 const Value: Boolean);
50831 begin
50832 BtnID := GetTBBtnGoodID( @Self, BtnID );
50833 Perform( TB_HIDEBUTTON, BtnID, Integer( not Value ) );
50834 end;
50836 {$IFDEF ASM_VERSION}
50837 //[function TControl.TBGetBtnStt]
50838 function TControl.TBGetBtnStt(BtnID: Integer; const Index: Integer): Boolean;
50840 PUSH 0
50841 PUSH ECX
50842 PUSH EAX
50843 CALL GetTBBtnGoodID
50844 POP EDX
50845 POP ECX
50846 PUSH EAX
50847 ADD ECX, 8
50848 PUSH ECX
50849 PUSH EDX
50850 CALL Perform
50851 TEST EAX, EAX
50852 SETNZ AL
50853 end;
50854 {$ELSE ASM_VERSION} //Pascal
50855 function TControl.TBGetBtnStt(BtnID: Integer; const Index: Integer): Boolean;
50856 begin
50857 BtnID := GetTBBtnGoodID( @Self, BtnID );
50858 Result := Perform( Index + 8, BtnID, 0 ) <> 0;
50859 end;
50860 {$ENDIF ASM_VERSION}
50863 //[procedure TControl.TBSetBtnStt]
50864 procedure TControl.TBSetBtnStt(BtnID: Integer; const Index: Integer; const Value: Boolean);
50865 begin
50866 BtnID := GetTBBtnGoodID( @Self, BtnID );
50867 Perform( Index, BtnID, Integer( Value ) );
50868 end;
50870 {$IFDEF ASM_VERSION}
50871 //[function TControl.TBIndex2Item]
50872 function TControl.TBIndex2Item(Idx: Integer): Integer;
50873 //*/////////////////////////////////////////////////////
50874 const //
50875 _sizeof_TTBButton = sizeof( TTBButton ); //
50876 //*/////////////////////////////////////////////////////
50878 //*/////////////////////////////////////////////////////
50879 // ADD ESP, -sizeof(TTBButton)
50880 //*/////////////////////////////////////////////////////
50881 ADD ESP, -_sizeof_TTBButton //
50882 //*/////////////////////////////////////////////////////
50883 PUSH ESP
50884 PUSH EDX
50885 PUSH TB_GETBUTTON
50886 PUSH EAX
50887 CALL Perform
50888 TEST EAX, EAX
50889 MOV EAX, [ESP].TTBButton.idCommand
50890 JNZ @@1
50891 OR EAX, -1
50892 //*/////////////////////////////////////////////////////
50893 //@@1: ADD ESP, sizeof( TTBButton )
50894 //*/////////////////////////////////////////////////////
50895 @@1: ADD ESP, _sizeof_TTBButton //
50896 //*/////////////////////////////////////////////////////
50897 end;
50898 {$ELSE ASM_VERSION} //Pascal
50899 function TControl.TBIndex2Item(Idx: Integer): Integer;
50900 var ButtonInfo: TTBButton;
50901 begin
50902 Result := -1;
50903 if Perform( TB_GETBUTTON, Idx, Integer( @ButtonInfo ) ) <> 0 then
50904 Result := ButtonInfo.idCommand;
50905 end;
50906 {$ENDIF ASM_VERSION}
50908 {$IFDEF ASM_VERSION}
50909 //[function TControl.TBGetButtonText]
50910 function TControl.TBGetButtonText( BtnID: Integer ): String;
50912 PUSH ECX
50913 ADD ESP, -1024
50914 PUSH ESP
50915 PUSH EAX
50916 CALL GetTBBtnGoodID
50917 POP EDX
50918 PUSH EAX
50919 PUSH TB_GETBUTTONTEXT
50920 PUSH EDX
50921 CALL Perform
50922 TEST EAX, EAX
50923 JLE @@2
50924 MOV EDX, ESP
50925 JMP @@1
50926 @@2: XOR EDX, EDX
50927 @@1: MOV EAX, [ESP+1024]
50928 CALL System.@LStrFromPChar
50929 ADD ESP, 1028
50930 end;
50931 {$ELSE ASM_VERSION} //Pascal
50932 function TControl.TBGetButtonText( BtnID: Integer ): String;
50933 var Buffer: array[ 0..1023 ] of Char;
50934 begin
50935 BtnID := GetTBBtnGoodID( @Self, BtnID );
50936 if Perform( TB_GETBUTTONTEXT, BtnID, Integer( @Buffer[ 0 ] ) ) > 0 then
50937 Result := Buffer
50938 else
50939 Result := '';
50940 end;
50941 {$ENDIF ASM_VERSION}
50944 //[function TControl.TBGetButtonRect]
50945 function TControl.TBGetButtonRect(BtnID: Integer): TRect;
50946 begin
50947 BtnID := GetTBBtnGoodID( @Self, BtnID );
50948 Perform( TB_GETITEMRECT, TBItem2Index( BtnID ), Integer( @Result ) );
50949 end;
50952 //[function TControl.TBGetRows]
50953 function TControl.TBGetRows: Integer;
50954 begin
50955 Result := 1;
50956 UpdateWndStyles;
50957 if (TBSTYLE_WRAPABLE and fStyle) <> 0 then
50958 Result := Perform( TB_GETROWS, 0, 0 );
50959 end;
50962 //[procedure TControl.TBSetRows]
50963 procedure TControl.TBSetRows(const Value: Integer);
50964 begin
50965 Perform( TB_SETROWS, Value, 0 );
50966 end;
50968 {$IFDEF ASM_VERSION}
50969 //[procedure TControl.TBSetTooltips]
50970 procedure TControl.TBSetTooltips(BtnID1st: Integer;
50971 Tooltips: array of PChar);
50973 PUSH EBX
50974 PUSH ESI
50975 MOV ESI, ECX
50976 MOV EBX, EAX
50977 PUSHAD
50978 MOV ECX, [EBX].fTBttCmd
50979 INC ECX
50980 LOOP @@1
50981 CALL NewList
50982 MOV [EBX].fTBttCmd, EAX
50983 CALL NewStrList
50984 MOV [EBX].fTBttTxt, EAX
50985 @@1: POPAD
50986 MOV ECX, [EBP+8]
50987 INC ECX
50988 JZ @@exit
50989 @@loop:
50990 PUSH ECX
50991 PUSH EDX
50992 PUSH 0
50993 LODSD
50994 MOV EDX, EAX
50995 MOV EAX, ESP
50996 CALL System.@LStrFromPChar
50998 MOV EDX, [ESP+4]
50999 MOV EAX, [EBX].fTBttCmd
51000 CALL TList.IndexOf
51001 TEST EAX, EAX
51002 JGE @@2
51004 MOV EDX, [ESP+4]
51005 MOV EAX, [EBX].fTBttCmd
51006 CALL TList.Add
51007 POP EDX
51008 PUSH EDX
51009 MOV EAX, [EBX].fTBttTxt
51010 CALL TStrList.Add
51011 JMP @@3
51013 @@2:
51014 MOV EDX, EAX
51015 POP ECX
51016 PUSH ECX
51017 MOV EAX, [EBX].fTBttTxt
51018 CALL TStrList.Put
51019 @@3:
51020 CALL RemoveStr
51022 POP EDX
51023 POP ECX
51024 INC EDX
51025 LOOP @@loop
51026 @@exit:
51027 POP ESI
51028 POP EBX
51029 end;
51030 {$ELSE ASM_VERSION} //Pascal
51031 procedure TControl.TBSetTooltips(BtnID1st: Integer;
51032 Tooltips: array of PChar);
51033 var I, J: Integer;
51034 begin
51035 if not assigned( fTBttCmd ) then
51036 begin
51037 fTBttCmd := NewList;
51038 fTBttTxt := NewStrList;
51039 end;
51040 for I:= 0 to High( Tooltips ) do
51041 begin
51042 J := fTBttCmd.IndexOf( Pointer( BtnID1st ) );
51043 if J < 0 then
51044 begin
51045 fTBttCmd.Add( Pointer( BtnID1st ) );
51046 fTBttTxt.Add( Tooltips[ I ] );
51048 else
51049 fTBttTxt.Items[ J ] := Tooltips[ I ];
51050 Inc( BtnID1st );
51051 end;
51052 end;
51053 {$ENDIF ASM_VERSION}
51055 {$IFDEF ASM_VERSION}
51056 //[function TControl.TBButtonAtPos]
51057 function TControl.TBButtonAtPos(X, Y: Integer): Integer;
51059 PUSH EAX
51060 CALL TBBtnIdxAtPos
51061 TEST EAX, EAX
51062 MOV EDX, EAX
51063 POP EAX
51064 JGE TBIndex2Item
51065 MOV EAX, EDX
51066 end;
51067 {$ELSE ASM_VERSION} //Pascal
51068 function TControl.TBButtonAtPos(X, Y: Integer): Integer;
51069 var I: Integer;
51070 begin
51071 I := TBBtnIdxAtPos( X, Y );
51072 if I >= 0 then
51073 I := TBIndex2Item( I );
51074 Result := I;
51075 end;
51076 {$ENDIF ASM_VERSION}
51078 {$IFDEF ASM_VERSION}
51079 //[function TControl.TBBtnIdxAtPos]
51080 function TControl.TBBtnIdxAtPos(X, Y: Integer): Integer;
51082 PUSH EBX
51083 PUSH ECX
51084 PUSH EDX
51085 MOV EBX, EAX
51086 CALL GetItemsCount
51087 MOV ECX, EAX
51088 JECXZ @@fin
51089 @@1: PUSH ECX
51090 ADD ESP, -16
51091 PUSH ESP
51092 DEC ECX
51093 PUSH ECX
51094 PUSH TB_GETITEMRECT
51095 PUSH EBX
51096 CALL Perform
51097 MOV EDX, ESP
51098 LEA EAX, [ESP+20]
51099 CALL PointInRect
51100 ADD ESP, 16
51101 POP ECX
51102 TEST AL, AL
51103 {$IFDEF USE_CMOV}
51104 CMOVNZ EAX, ECX
51105 {$ELSE}
51106 JZ @@2
51107 MOV EAX, ECX
51108 JMP @@fin
51109 @@2: {$ENDIF}
51110 JNZ @@fin
51112 LOOP @@1
51113 @@fin: DEC EAX
51114 POP EDX
51115 POP EDX
51116 POP EBX
51117 end;
51118 {$ELSE ASM_VERSION} //Pascal
51119 function TControl.TBBtnIdxAtPos(X, Y: Integer): Integer;
51120 var I: Integer;
51121 R: TRect;
51122 P: TPoint;
51123 begin
51124 P := MakePoint( X, Y );
51125 for I := TBButtonCount - 1 downto 0 do
51126 begin
51127 Perform( TB_GETITEMRECT, I, Integer( @R ) );
51128 if PointInRect( P, R ) then
51129 begin
51130 Result := I;
51131 Exit;
51132 end;
51133 end;
51134 Result := -1;
51135 end;
51136 {$ENDIF ASM_VERSION}
51139 //[procedure TControl.TBDeleteButton]
51140 procedure TControl.TBDeleteButton(BtnID: Integer);
51141 begin
51142 BtnID := GetTBBtnGoodID( @Self, BtnID );
51143 Perform( TB_DELETEBUTTON, TBItem2Index( BtnID ), 0 );
51144 end;
51147 //[procedure TControl.TBDeleteBtnByIdx]
51148 procedure TControl.TBDeleteBtnByIdx(Idx: Integer);
51149 begin
51150 Perform( TB_DELETEBUTTON, Idx, 0 );
51151 end;
51154 //[procedure TControl.Clear]
51155 procedure TControl.Clear;
51156 begin
51157 fCommandActions.aClear( @Self );
51158 end;
51160 {$IFDEF ASM_noVERSION}
51161 //[function TControl.TBGetBtnImgIdx]
51162 function TControl.TBGetBtnImgIdx(BtnID: Integer): Integer;
51163 const szTBButton = sizeof( TTBButton );
51165 ADD ESP, -szTBButton
51166 PUSH ESP
51167 PUSH EAX
51168 CALL TBItem2Index
51169 POP EDX
51170 PUSH EAX
51171 PUSH TB_GETBUTTON
51172 PUSH EDX
51173 CALL Perform
51174 POP EAX
51175 ADD ESP, szTBButton-4
51176 end;
51177 {$ELSE ASM_VERSION} //Pascal
51178 function TControl.TBGetBtnImgIdx(BtnID: Integer): Integer;
51179 var B: TTBButton;
51180 begin
51181 Perform( TB_GETBUTTON, TBItem2Index( GetTBBtnGoodID( @Self, BtnID ) ), Integer( @B ) );
51182 Result := B.iBitmap;
51183 end;
51184 {$ENDIF ASM_VERSION}
51187 //[procedure TControl.TBSetBtnImgIdx]
51188 procedure TControl.TBSetBtnImgIdx(BtnID: Integer; const Value: Integer);
51189 begin
51190 Perform( TB_CHANGEBITMAP, GetTBBtnGoodID( @Self, BtnID ), Value );
51191 end;
51193 {$IFDEF ASM_VERSION}
51194 //[procedure TControl.TBSetButtonText]
51195 procedure TControl.TBSetButtonText(BtnID: Integer; const Value: String);
51197 PUSH 0
51198 PUSH ECX
51199 PUSH EAX
51200 CALL GetTBBtnGoodID
51201 POP EDX
51203 ADD ESP, -16
51204 PUSH TBIF_TEXT
51205 PUSH 32 //Sizeof( TTBButtonInfo )
51206 PUSH ESP
51207 PUSH EAX
51208 PUSH TB_SETBUTTONINFO
51209 PUSH EDX
51210 CALL Perform
51211 ADD ESP, 32 //sizeof( TTBButtonInfo )
51212 end;
51213 {$ELSE ASM_VERSION} //Pascal
51214 procedure TControl.TBSetButtonText(BtnID: Integer; const Value: String);
51215 var BI: TTBButtonInfo;
51216 begin
51217 BtnID := GetTBBtnGoodID( @Self, BtnID );
51218 BI.cbSize := Sizeof( BI );
51219 BI.dwMask := TBIF_TEXT;
51220 BI.pszText := PChar( Value );
51221 Perform( TB_SETBUTTONINFO, BtnID, Integer( @BI ) );
51222 end;
51223 {$ENDIF ASM_VERSION}
51225 {$IFDEF ASM_VERSION}
51226 //[function TControl.TBGetBtnWidth]
51227 function TControl.TBGetBtnWidth(BtnID: Integer): Integer;
51229 ADD ESP, -16
51230 MOV ECX, ESP
51231 CALL TBGetButtonRect
51232 POP EDX
51233 POP ECX
51234 POP EAX
51235 SUB EAX, EDX
51236 POP EDX
51237 end;
51238 {$ELSE ASM_VERSION} //Pascal
51239 function TControl.TBGetBtnWidth(BtnID: Integer): Integer;
51240 var R: TRect;
51241 begin
51242 R := TBButtonRect[ BtnID ];
51243 Result := R.Right - R.Left;
51244 end;
51245 {$ENDIF ASM_VERSION}
51247 {$IFDEF ASM_VERSION}
51248 //[procedure TControl.TBSetBtnWidth]
51249 procedure TControl.TBSetBtnWidth(BtnID: Integer; const Value: Integer);
51251 PUSH EBX
51252 MOV EBX, ECX
51254 PUSH EAX
51255 CALL GetTBBtnGoodID
51256 POP EDX
51258 ADD ESP, -24
51259 PUSH TBIF_SIZE or TBIF_STYLE
51260 PUSH 32
51261 MOV ECX, ESP
51263 PUSH ECX
51264 PUSH EAX
51265 PUSH TB_SETBUTTONINFO
51266 PUSH EDX
51268 PUSH ECX
51269 PUSH EAX
51270 PUSH TB_GETBUTTONINFO
51271 PUSH EDX
51272 CALL Perform
51274 MOV [ESP+16+18], BX
51275 AND byte ptr [ESP+16].TTBButtonInfo.fsStyle, not TBSTYLE_AUTOSIZE
51276 CALL Perform
51277 ADD ESP, 32
51278 POP EBX
51279 end;
51280 {$ELSE ASM_VERSION} //Pascal
51281 procedure TControl.TBSetBtnWidth(BtnID: Integer; const Value: Integer);
51282 var BI: TTBButtonInfo;
51283 begin
51284 BI.cbSize := Sizeof( BI );
51285 BI.dwMask := TBIF_SIZE or TBIF_STYLE;
51286 BtnID := GetTBBtnGoodID( @Self, BtnID );
51287 Perform( TB_GETBUTTONINFO, BtnID, Integer( @BI ) );
51288 BI.cx := Value;
51289 BI.fsStyle := BI.fsStyle and not TBSTYLE_AUTOSIZE;
51290 Perform( TB_SETBUTTONINFO, BtnID, Integer( @BI ) );
51291 end;
51292 {$ENDIF ASM_VERSION}
51294 //[procedure TControl.TBSetBtMinMaxWidth]
51295 procedure TControl.TBSetBtMinMaxWidth(const Idx: Integer; const Value: Integer);
51296 begin
51297 case Idx of
51298 0: FTBBtMinWidth := Value;
51299 1: FTBBtMaxWidth := Value;
51300 end;
51301 Perform( TB_SETBUTTONWIDTH, 0, FTBBtMaxWidth or (FTBBtMinWidth shl 16) );
51302 end;
51304 {$IFDEF F_P}
51305 //[function TControl.TBGetBtMinMaxWidth]
51306 function TControl.TBGetBtMinMaxWidth(const Idx: Integer): Integer;
51307 begin
51308 CASE Idx OF
51309 0: Result := FTBBtMinWidth;
51310 1: Result := FTBBtMaxWidth;
51311 END;
51312 end;
51313 {$ENDIF F_P}
51315 //[procedure TControl.SetDroppedDown]
51316 procedure TControl.SetDroppedDown(const Value: Boolean);
51317 begin
51318 //fDropped := Value;
51319 Perform( CB_SHOWDROPDOWN, Integer( Value ), 0 );
51320 end;
51322 {$IFDEF ASM_VERSION}
51323 //[procedure TControl.AddDirList]
51324 procedure TControl.AddDirList(const Filemask: String; Attrs: DWORD);
51326 CALL EDX2PChar
51327 PUSH EDX
51328 PUSH ECX
51329 MOVZX ECX, [EAX].fCommandActions.aDir
51330 JECXZ @@exit
51331 PUSH ECX
51332 PUSH EAX
51333 CALL Perform
51335 @@exit:
51336 POP ECX
51337 POP ECX
51338 end;
51339 {$ELSE ASM_VERSION} //Pascal
51340 procedure TControl.AddDirList(const Filemask: String; Attrs: DWORD);
51341 begin
51342 if fCommandActions.aDir <> 0 then
51343 Perform( fCommandActions.aDir, Attrs, Integer( PChar( Filemask ) ) );
51344 end;
51345 {$ENDIF ASM_VERSION}
51347 //[FUNCTION WndProcShowModal]
51348 {$IFDEF ASM_VERSION}
51349 function WndProcShowModal( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
51351 CMP word ptr [EDX].TMsg.message, WM_CLOSE
51352 JNZ @@ret_false
51353 {//++++++ AP
51354 PUSH EBX
51355 MOV EBX, 1
51356 CMP [EAX].TControl.fOnClose.TMethod.Code, 0
51357 JZ @@AP1
51358 PUSH EAX
51359 PUSH EDX
51360 PUSH ECX
51361 XCHG EDX, EAX
51362 PUSH EBX
51363 MOV ECX, ESP
51364 MOV EAX, [EDX].TControl.fOnClose.TMethod.Data
51365 CALL dword ptr [EDX].TControl.fOnClose.TMethod.Code
51366 POP EBX
51367 POP ECX
51368 POP EDX
51369 POP EAX
51370 @@AP1:
51371 //------ AP}
51373 XCHG EDX, EAX
51374 XOR EAX, EAX
51375 CMP [EDX].TControl.fModalResult, EAX
51376 JNZ @@1
51377 OR [EDX].TControl.fModalResult, -1
51378 @@1:
51379 {//++++++ AP
51380 TEST BL, BL
51381 JNZ @@AP2
51382 MOV [EDX].TControl.fModalResult, 0
51383 @@AP2:
51384 POP EBX
51385 //------ AP}
51387 MOV [ECX], EAX
51388 INC EAX
51390 @@ret_false:
51391 XOR EAX, EAX
51393 end;
51394 {$ELSE ASM_VERSION} //Pascal
51395 function WndProcShowModal( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
51396 //var Accept: Boolean; // {Alexander Pravdin, AP}
51397 begin
51398 if Msg.message = WM_CLOSE then
51399 begin
51400 //++++++++ {AP} +++++++++++++++++++++++++++++++++++++++++++++++++++++++//
51401 {Accept := True; //
51402 if Assigned( Self_.fOnClose ) then Self_.fOnClose( Self_, Accept ); //
51403 }//-------- {AP} ----------------------------------------------------//
51404 if Self_.ModalResult = 0 then { (Sergey Shishmintzev) }
51405 Self_.ModalResult := -1;
51406 //++++++++ {AP} +++++++++++++++++++++++++++++++++++++++++++++++++++++++//
51407 {if not Accept then //
51408 Self_.ModalResult := 0; //íå çàêðûâàåì ôîðìó, îñòàâëÿÿ å¸ íà ýêðàíå//
51409 }//-------- {AP} ----------------------------------------------------//
51410 Rslt := 0;
51411 Result := True; // Do not process !
51413 else
51414 Result := False;
51415 end;
51416 {$ENDIF ASM_VERSION}
51417 //[END WndProcShowModal]
51419 {$IFDEF ASM_noVERSION}
51420 //[function TControl.ShowModal]
51421 function TControl.ShowModal: Integer;
51423 MOV ECX, [EAX].fParent
51424 JECXZ @@show
51425 MOVZX ECX, [EAX].fIsControl
51426 JECXZ @@show_modal
51427 @@show:
51428 CALL Show
51429 XOR EAX, EAX
51431 @@show_modal:
51432 PUSHAD
51434 MOV EBX, EAX
51435 MOV EDI, [Applet]
51437 XOR EBP, EBP // CurCtl = nil
51439 MOV EAX, [EDI].fCurrentControl
51440 CMP [EDI].TControl.FIsApplet, 0
51441 {$IFDEF USE_CMOV}
51442 CMOVZ EAX, EDI
51443 {$ELSE}
51444 JNZ @@curctrl_save
51445 MOV EAX, EDI
51446 @@curctrl_save:
51447 {$ENDIF}
51449 PUSH EAX
51451 MOV EDX, offset[WndProcShowModal]
51452 PUSH EDX
51454 MOV EAX, EBX
51455 CALL TControl.AttachProc
51456 XOR EDX, EDX
51457 MOV [EBX].fModalResult, EDX
51459 CALL NewList
51460 XCHG EAX, EBP
51462 XOR ECX, ECX
51463 INC ECX
51464 MOV ESI, EDI
51466 CMP [EDI].TControl.FIsApplet, 0
51467 JZ @@isapplet
51469 MOV EBP, [EDI].fCurrentControl // CurCtl = Applet.fCurrentControl
51471 MOV ESI, [EDI].fChildren
51472 MOV ECX, [ESI].TList.fCount
51473 MOV ESI, [ESI].TList.fItems
51475 @@1loo: LODSD
51477 @@isapplet:
51479 PUSH ECX
51480 CMP EAX, EBX
51481 JE @@1nx
51482 PUSH EAX
51483 CALL GetEnabled
51484 TEST AL, AL
51485 POP EAX
51486 JZ @@1nx
51487 PUSH EAX
51488 MOV DL, 0
51489 CALL SetEnabled
51490 POP EDX
51491 MOV EAX, EBP
51492 CALL TList.Add
51493 @@1nx: POP ECX
51494 LOOP @@1loo
51496 INC [EBX].fModal
51497 MOV EAX, [Applet]
51498 MOV [EAX].fModalForm, EBX
51500 MOV EAX, EBX
51501 CALL Show
51503 @@msgloo:
51504 MOVZX ECX, [AppletTerminated]
51505 OR ECX, [EBX].fModalResult
51506 JNZ @@e_msgloo
51507 CALL WaitMessage
51508 MOV EAX, EDI
51509 CALL ProcessMessages
51510 {$IFNDEF NOT_USE_OnIdle}
51511 MOV EAX, EBX
51512 CALL [ProcessIdle]
51513 {$ENDIF}
51514 JMP @@msgloo
51516 @@e_msgloo:
51517 POP EDX
51518 MOV EAX, EBX
51519 CALL TControl.DetachProc
51521 DEC [EBX].fModal
51522 MOV EAX, [Applet]
51523 XOR ECX, ECX
51524 MOV [EAX].fModalForm, ECX
51526 MOV ECX, [EBP].TList.fCount
51527 JECXZ @@2end
51528 MOV ESI, [EBP].TList.fItems
51530 @@2loo: LODSD
51531 PUSH ECX
51532 MOV DL, 1
51533 CALL TControl.SetEnabled
51534 POP ECX
51535 LOOP @@2loo
51537 @@2end:
51538 MOV EAX, EBP
51539 CALL TObj.Free
51541 POP ECX
51542 JECXZ @@exit
51543 PUSH 0
51544 PUSH WA_ACTIVE
51545 PUSH WM_ACTIVATE
51546 PUSH [ECX].fHandle
51547 CALL PostMessage
51549 TEST EBP, EBP // CurCtl = nil ?
51550 JZ @@exit
51551 MOV EAX, EBP
51552 MOV DL, 1
51553 CALL TControl.SetFocused
51555 @@exit:
51556 POPAD
51557 MOV EAX, [EAX].fModalResult
51558 end;
51559 {$ELSE ASM_VERSION} //Pascal
51560 {$IFDEF USE_SHOWMODALPARENTED_ALWAYS}
51561 function TControl.ShowModal: Integer;
51562 begin
51563 Result := ShowModalParented(Applet);
51564 end;
51565 {$ELSE not USE_SHOWMODALPARENTED_ALWAYS}
51566 function TControl.ShowModal: Integer;
51567 var FL: PList;
51568 var CurForm: PControl;
51569 I: Integer;
51570 F: PControl;
51571 CurCtl: PControl; // { Alexander Pravdin }
51572 begin
51573 Result := 0;
51574 if (fIsControl) or (fParent = nil) then
51575 begin
51576 Show;
51577 Exit;
51578 end;
51579 AttachProc( WndProcShowModal );
51580 CurForm := Applet.fCurrentControl;
51581 FL := NewList;
51582 CurCtl := nil; // { Alexander Pravdin }
51584 if Applet.IsApplet then
51585 for I := 0 to Applet.ChildCount - 1 do
51586 begin
51587 F := Applet.fChildren.Items[ I ];
51588 if F <> @Self then
51589 if F.Enabled then
51590 begin
51591 FL.Add( F );
51592 F.Enabled := FALSE;
51593 end;
51595 else
51596 begin
51597 CurForm := Applet;
51598 if Applet.Enabled then
51599 begin
51600 FL.Add( Applet );
51601 CurCtl := Applet.fCurrentControl; { Alexander Pravdin }
51602 Applet.Enabled := FALSE;
51603 end;
51604 end;
51606 Inc( fModal );
51607 Applet.fModalForm := @ Self;
51608 Enabled := TRUE;
51610 Show;
51611 ModalResult := 0;
51612 while not AppletTerminated and (ModalResult = 0) do
51613 begin
51614 WaitMessage;
51615 Applet.ProcessMessages;
51616 {$IFNDEF NOT_USE_OnIdle}
51617 ProcessIdle( @Self );
51618 {$ENDIF}
51619 end;
51621 Dec( fModal );
51622 Applet.fModalForm := nil;
51624 DetachProc( WndProcShowModal );
51625 for I := 0 to FL.Count - 1 do
51626 begin
51627 F := FL.Items[ I ];
51628 F.Enabled := TRUE;
51629 //EnableWindow( F.Handle, TRUE );
51630 //F.Perform( WM_ENABLE, 1, 0 );
51631 end;
51632 FL.Free;
51634 if CurForm <> nil then
51635 PostMessage( CurForm.Handle, WM_ACTIVATE, WA_ACTIVE, 0 );
51636 if CurCtl <> nil then CurCtl.SetFocused( TRUE ); { Alexander Pravdin }
51638 Result := ModalResult;
51639 end;
51640 {$ENDIF USE_SHOWMODALPARENTED_ALWAYS}
51641 {$ENDIF ASM_VERSION}
51643 //[function TControl.ShowModalParented]
51644 {$IFNDEF NEW_MODAL}
51645 function TControl.ShowModalParented( const AParent: PControl ): Integer;
51646 begin
51647 Result := 0;
51648 end;
51649 {$ELSE NEW_MODAL defined}
51650 function TControl.ShowModalParented( const AParent: PControl ): Integer;
51652 FL: PList;
51653 OldMF, F: PControl;
51654 I: Integer;
51655 begin
51656 Result := 0;
51657 if ( AParent = nil ) then Exit;
51659 Inc( fModal );
51660 FL := NewList;
51661 OldMF := AParent.fModalForm;
51662 AParent.fModalForm := @Self;
51664 if AParent.fIsApplet or ( AParent.IsMainWindow and AParent.fIsForm ) then
51665 begin
51666 for I := 0 to AParent.ChildCount - 1 do
51667 begin
51668 F := AParent.fChildren.Items[ I ];
51669 if ( F <> @Self ) and F.fIsForm and F.fEnabled and F.fVisible then
51670 begin
51671 FL.Add( F );
51672 F.Enabled := FALSE;
51673 end;
51674 end;
51675 end;
51677 if AParent.fIsForm and AParent.Enabled then
51678 begin
51679 FL.Add( AParent );
51680 AParent.Enabled := FALSE;
51681 end;
51683 ModalResult := 0;
51684 Show;
51685 while not AppletTerminated and ( ModalResult = 0 ) do
51686 begin
51687 WaitMessage;
51688 AParent.ProcessMessages;
51689 {$IFNDEF NOT_USE_OnIdle}
51690 ProcessIdle( @Self );
51691 {$ENDIF}
51692 end;
51694 AParent.fModalForm := OldMF;
51695 Dec( fModal );
51696 for I := 0 to FL.Count - 1 do
51697 PControl( FL.Items[ I ] ).Enabled := True;
51698 FL.Free;
51699 Hide;
51700 Result := ModalResult;
51701 end;
51702 {$ENDIF NEW_MODAL}
51704 //[function DisableWindows]
51705 function DisableWindows( W: hwnd; LPARAM: Integer ): Bool; stdcall;
51706 var FL: PList;
51707 Buf: array[ 0..127 ] of Char;
51708 begin
51709 FL := Pointer( LPARAM );
51710 if IsWindowEnabled( W ) and (W <> FL.Tag) then
51711 begin
51712 GetClassName( W, @ Buf[ 0 ], Sizeof( Buf ) );
51713 if Buf <> 'ComboLBox' then
51714 begin
51715 FL.Add( Pointer( W ) );
51716 EnableWindow( W, FALSE );
51717 end;
51718 end;
51719 Result := TRUE;
51720 end;
51722 //[function TControl.ShowModalEx]
51723 function TControl.ShowModalEx: Integer;
51724 var FL: PList;
51725 var CurForm: PControl;
51726 I: Integer;
51727 W: HWnd;
51728 CurCtl: PControl; { Alexander Pravdin }
51729 begin
51730 Result := 0;
51731 if (fIsControl) or (fParent = nil) then
51732 begin
51733 Show;
51734 Exit;
51735 end;
51736 AttachProc( WndProcShowModal );
51737 CurForm := Applet.fCurrentControl;
51738 FL := NewList;
51739 FL.Tag := fHandle;
51741 // ++++ { Alexander Pravdin }
51742 if not Applet.fIsApplet then CurCtl := Applet.fCurrentControl
51743 else CurCtl := nil;
51744 // ----
51745 CreateWindow;
51747 EnumThreadWindows( GetCurrentThreadID, @ DisableWindows, Integer( FL ) );
51748 Enabled := TRUE;
51750 Inc( fModal );
51751 Applet.fModalForm := @ Self;
51752 Show;
51753 ModalResult := 0;
51754 while not AppletTerminated and (ModalResult = 0) do
51755 begin
51756 WaitMessage;
51757 Applet.ProcessMessages;
51758 {$IFNDEF NOT_USE_OnIdle}
51759 ProcessIdle( @Self );
51760 {$ENDIF}
51761 end;
51763 Dec( fModal );
51764 Applet.fModalForm := @ Self;
51766 DetachProc( WndProcShowModal );
51768 for I := 0 to FL.Count - 1 do
51769 begin
51770 W := THandle( FL.Items[ I ] );
51771 EnableWindow( W, TRUE );
51772 end;
51773 FL.Free;
51775 if CurForm <> nil then
51776 PostMessage( CurForm.Handle, WM_ACTIVATE, WA_ACTIVE, 0 );
51777 if CurCtl <> nil then CurCtl.SetFocused( True ); { Alexander Pravdin }
51778 Result := ModalResult;
51779 end;
51781 //[function TControl.GetModal]
51782 function TControl.GetModal: Boolean;
51783 begin
51784 Result := fModal > 0;
51785 end;
51787 {$IFDEF USE_SETMODALRESULT}
51788 //[procedure TControl.SetModalResult]
51789 procedure TControl.SetModalResult( const Value: Integer );
51790 begin
51791 //if fModal <= 0 then Exit;
51792 fModalResult := Value;
51793 if Value <> 0 then
51794 PostMessage( GetWindowHandle, 0, 0, 0 );
51795 end;
51796 {$ENDIF}
51799 //////////////////////////////////////////////////////////////////
51801 // T I M E R
51803 //////////////////////////////////////////////////////////////////
51805 var TimerOwnerWnd: PControl;
51806 TimerCount: Integer = 0;
51808 { -- Constructor of timer -- }
51810 //[function NewTimer]
51811 function NewTimer( Interval: Integer ): PTimer;
51812 begin
51814 New( Result, Create );
51815 {+}{++}(*Result := PTimer.Create;*){--}
51816 if Interval <= 0 then Interval := 1000;
51817 Result.fInterval := Interval;
51818 Inc( TimerCount );
51819 end;
51820 //[END NewTimer]
51822 { -- Timer procedure -- }
51824 //[FUNCTION TimerProc]
51825 {$IFDEF ASM_VERSION}
51826 function TimerProc( Wnd : HWnd; Msg : Integer; T : PTimer; CurrentTime : DWord ): Integer;
51827 stdcall;
51828 asm //cmd //opd
51829 MOV EDX, T
51830 MOV ECX, [EDX].TTimer.fOnTimer.TMethod.Code
51831 JECXZ @@exit
51832 MOV EAX, [EDX].TTimer.fOnTimer.TMethod.Data
51833 CALL ECX
51834 @@exit: XOR EAX, EAX
51835 end;
51836 {$ELSE ASM_VERSION} //Pascal
51837 function TimerProc( Wnd : HWnd; Msg : Integer; T : PTimer; CurrentTime : DWord ): Integer;
51838 stdcall;
51839 begin
51840 if Assigned( T.fOnTimer ) then
51841 T.fOnTimer( T );
51842 Result := 0;
51843 end;
51844 {$ENDIF ASM_VERSION}
51845 //[END TimerProc]
51847 { TTimer }
51849 {$IFDEF ASM_VERSION}
51850 //[destructor TTimer.Destroy]
51851 destructor TTimer.Destroy;
51853 PUSH EAX
51854 XOR EDX, EDX
51855 CALL TTimer.SetEnabled
51856 POP EAX
51857 CALL TObj.Destroy
51858 DEC [TimerCount]
51859 JNZ @@exit
51860 XOR EAX, EAX
51861 XCHG EAX, [TimerOwnerWnd]
51862 CALL TObj.Free
51863 @@exit:
51864 end;
51865 {$ELSE ASM_VERSION} //Pascal
51866 destructor TTimer.Destroy;
51867 begin
51868 Enabled := False;
51869 inherited;
51870 Dec( TimerCount );
51871 if TimerCount = 0 then
51872 begin
51873 TimerOwnerWnd.Free;
51874 TimerOwnerWnd := nil;
51875 end;
51876 end;
51877 {$ENDIF ASM_VERSION}
51879 {$IFDEF ASM_VERSION}
51880 //[procedure TTimer.SetEnabled]
51881 procedure TTimer.SetEnabled(const Value: Boolean);
51883 PUSH EBX
51884 XCHG EBX, EAX
51886 CMP [EBX].fEnabled, DL
51887 JZ @@exit
51889 MOV [EBX].fEnabled, DL
51891 TEST DL, DL
51892 JZ @@disable
51894 MOV ECX, [TimerOwnerWnd]
51895 INC ECX
51896 LOOP @@owner_ready
51898 INC ECX
51899 MOV EDX, offset[EmptyString]
51900 XOR EAX, EAX
51901 CALL _NewWindowed
51902 MOV [TimerOwnerWnd], EAX
51903 MOV [EAX].TControl.fStyle, 0
51904 INC [EAX].TControl.fIsControl
51905 XCHG ECX, EAX
51907 @@owner_ready:
51909 PUSH offset[TimerProc]
51910 PUSH [EBX].fInterval
51911 PUSH EBX
51912 XCHG EAX, ECX
51913 CALL TControl.GetWindowHandle
51914 PUSH EAX
51915 CALL SetTimer
51916 MOV [EBX].fHandle, EAX
51918 JMP @@exit
51920 @@disable:
51921 XOR ECX, ECX
51922 XCHG ECX, [EBX].TTimer.fHandle
51923 JECXZ @@exit
51925 PUSH ECX
51926 MOV EAX, [TimerOwnerWnd]
51927 PUSH [EAX].TControl.fHandle
51928 CALL KillTimer
51930 @@exit:
51931 POP EBX
51932 end;
51933 {$ELSE ASM_VERSION} //Pascal
51934 procedure TTimer.SetEnabled(const Value: Boolean);
51935 begin
51936 if FEnabled = Value then Exit;
51937 fEnabled := Value;
51938 if Value then
51939 begin
51940 if TimerOwnerWnd = nil then
51941 begin
51942 TimerOwnerWnd := _NewWindowed( nil, '', TRUE );
51943 TimerOwnerWnd.fStyle := 0;
51944 TimerOwnerWnd.fIsControl := TRUE;
51945 end;
51946 fHandle := SetTimer( TimerOwnerWnd.GetWindowHandle, Integer( @Self ),
51947 fInterval, @TimerProc );
51949 else
51950 begin
51951 if fHandle <> 0 then
51952 begin
51953 KillTimer( TimerOwnerWnd.fHandle, fHandle );
51954 fHandle := 0;
51955 end;
51956 end;
51957 end;
51958 {$ENDIF ASM_VERSION}
51960 {$IFDEF ASM_VERSION}
51961 //[procedure TTimer.SetInterval]
51962 procedure TTimer.SetInterval(const Value: Integer);
51964 CMP EDX, [EAX].fInterval
51965 JE @@exit
51966 MOV [EAX].fInterval, EDX
51967 PUSH dword ptr [EAX].fEnabled
51968 PUSH EAX
51969 XOR EDX, EDX
51970 CALL SetEnabled
51971 POP EAX
51972 POP EDX
51973 CALL SetEnabled
51974 @@exit:
51975 end;
51976 {$ELSE ASM_VERSION} //Pascal
51977 procedure TTimer.SetInterval(const Value: Integer);
51978 var WasEnabled : Boolean;
51979 begin
51980 if fInterval = Value then Exit;
51981 fInterval := Value;
51982 WasEnabled := Enabled;
51983 Enabled := False;
51984 Enabled := WasEnabled;
51985 end;
51986 {$ENDIF ASM_VERSION}
51989 { TMMTimer }
51991 { ------------ declarations moved here from MMSystem -------------------- }
51992 const
51993 TIME_ONESHOT = 0; { program timer for single event }
51994 TIME_PERIODIC = 1; { program for continuous periodic event }
51995 TIME_CALLBACK_FUNCTION = $0000; { callback is function }
51996 TIME_CALLBACK_EVENT_SET = $0010; { callback is event - use SetEvent }
51997 TIME_CALLBACK_EVENT_PULSE = $0020; { callback is event - use PulseEvent }
51999 type
52000 TFNTimeCallBack = procedure(uTimerID, uMessage: UINT;
52001 dwUser, dw1, dw2: DWORD) stdcall;
52002 //[API timeSetEvent]
52003 function timeSetEvent(uDelay, uResolution: UINT;
52004 lpFunction: TFNTimeCallBack; dwUser: DWORD; uFlags: UINT): THandle; stdcall;
52005 external 'winmm.dll' name 'timeSetEvent';
52006 function timeKillEvent(uTimerID: UINT): Integer; stdcall;
52007 external 'winmm.dll' name 'timeKillEvent';
52008 { ----------------------------------------------------------------------- }
52010 //[procedure MMTimerCallback]
52011 procedure MMTimerCallback(uTimerID, uMessage: UINT; dwUser, dw1, dw2: DWORD);
52012 stdcall;
52013 var MMTimer: PMMTimer;
52014 begin
52015 MMTimer := Pointer( dwUser );
52016 if Assigned( MMTimer.FOnTimer ) then
52017 MMTimer.fOnTimer( MMTimer );
52018 end;
52020 //[function NewMMTimer]
52021 function NewMMTimer( Interval: Integer ): PMMTimer;
52022 begin
52024 New( Result, Create );
52025 {+} {++}(* Result := PMMTimer.Create; *){--}
52026 Result.fInterval := Interval;
52027 Result.FPeriodic := TRUE;
52028 end;
52029 //[END NewMMTimer]
52031 //[destructor TMMTimer.Destroy]
52032 destructor TMMTimer.Destroy;
52033 begin
52034 Enabled := FALSE;
52035 Inc( TimerCount );
52036 inherited;
52037 end;
52039 //[procedure TMMTimer.SetEnabled]
52040 procedure TMMTimer.SetEnabled(const Value: Boolean);
52041 begin
52042 if Value xor (fHandle <> 0) then
52043 begin
52044 if fHandle = 0 then
52045 fHandle := timeSetEvent( Interval, Resolution, MMTimerCallback, DWORD( @ Self ),
52046 Integer( Periodic ) or TIME_CALLBACK_FUNCTION )
52047 else
52048 begin
52049 timeKillEvent( fHandle );
52050 fHandle := 0;
52051 end;
52052 end;
52053 fEnabled := Value;
52054 end;
52066 ////////////////////////////////////////////////////////////////////////
52069 // t B I T M A P
52072 ///////////////////////////////////////////////////////////////////////
52074 { -- bitmap -- }
52076 //[FUNCTION PrepareBitmapHeader]
52077 {$IFDEF ASM_VERSION}
52078 function PrepareBitmapHeader( W, H, BitsPerPixel: Integer ): PBitmapInfo;
52079 const szIH = sizeof(TBitmapInfoHeader);
52080 szHd = szIH + 256 * Sizeof(TRGBQuad);
52082 PUSH EDI
52084 PUSH ECX // BitsPerPixel
52085 PUSH EDX // H
52086 PUSH EAX // W
52088 MOV EAX, szHd
52089 CALL AllocMem
52091 MOV EDI, EAX
52092 XCHG ECX, EAX
52094 XOR EAX, EAX
52095 MOV AL, szIH
52096 STOSD // biSize = Sizeof( TBitmapInfoHeader )
52097 POP EAX // ^ W
52098 STOSD // -> biWidth
52099 POP EAX // ^ H
52100 STOSD // -> biHeight
52101 XOR EAX, EAX
52102 INC EAX
52103 STOSW // 1 -> biPlanes
52104 POP EAX // ^ BitsPerPixel
52105 STOSW // -> biBitCount
52107 XCHG EAX, ECX // EAX = Result
52108 POP EDI
52109 end;
52110 {$ELSE ASM_VERSION} //Pascal
52111 function PrepareBitmapHeader( W, H, BitsPerPixel: Integer ): PBitmapInfo;
52112 begin
52113 Assert( W > 0, 'Width must be >0' );
52114 Assert( H > 0, 'Height must be >0' );
52116 Result := AllocMem( 256*Sizeof(TRGBQuad)+Sizeof(TBitmapInfoHeader) );
52117 Assert( Result <> nil, 'No memory' );
52119 Result.bmiHeader.biSize := Sizeof( TBitmapInfoHeader );
52120 Result.bmiHeader.biWidth := W;
52121 Result.bmiHeader.biHeight := H; // may be, -H ?
52122 Result.bmiHeader.biPlanes := 1;
52123 Result.bmiHeader.biBitCount := BitsPerPixel;
52124 //Result.bmiHeader.biCompression := BI_RGB; // BI_RGB = 0
52125 end;
52126 {$ENDIF ASM_VERSION}
52127 //[END PrepareBitmapHeader]
52129 const
52130 BitsPerPixel_By_PixelFormat: array[ TPixelFormat ] of Byte =
52131 ( 0, 1, 4, 8, 16, 16, 24, 32, 0 );
52133 //[FUNCTION Bits2PixelFormat]
52134 {$IFDEF ASM_VERSION}
52135 function Bits2PixelFormat( BitsPerPixel: Integer ): TPixelFormat;
52137 PUSH ESI
52138 MOV ESI, offset[ BitsPerPixel_By_PixelFormat + 1 ]
52139 XOR ECX, ECX
52140 XCHG EDX, EAX
52141 @@loo: INC ECX
52142 LODSB
52143 CMP AL, DL
52144 JZ @@exit
52145 TEST AL, AL
52146 JNZ @@loo
52147 @@exit: XCHG EAX, ECX
52148 POP ESI
52149 end;
52150 {$ELSE ASM_VERSION} //Pascal
52151 function Bits2PixelFormat( BitsPerPixel: Integer ): TPixelFormat;
52152 var I: TPixelFormat;
52153 begin
52154 for I := High(I) downto Low(I) do
52155 if BitsPerPixel = BitsPerPixel_By_PixelFormat[ I ] then
52156 begin
52157 Result := I;
52158 Exit;
52159 end;
52160 Result := pfDevice;
52161 end;
52162 {$ENDIF ASM_VERSION}
52163 //[END Bits2PixelFormat]
52165 //[procedure DummyDetachCanvas]
52166 procedure DummyDetachCanvas( Sender: PBitmap );
52167 begin
52168 end;
52170 //[FUNCTION _NewBitmap]
52171 {$IFDEF ASM_VERSION}
52172 function _NewBitmap( W, H: Integer ): PBitmap;
52173 begin
52174 New( Result, Create );
52175 Result.fDetachCanvas := DummyDetachCanvas;
52176 Result.fWidth := W;
52177 Result.fHeight := H;
52178 end;
52179 {$ENDIF ASM_VERSION}
52180 //[END _NewBitmap]
52182 //[FUNCTION NewBitmap]
52183 {$IFDEF ASM_VERSION}
52184 function NewBitmap( W, H: Integer ): PBitmap;
52186 PUSH EAX
52187 PUSH EDX
52188 CALL _NewBitmap
52189 POP EDX
52190 POP ECX
52191 PUSH EAX
52192 INC [EAX].TBitmap.fHandleType
52193 JECXZ @@exit
52194 TEST EDX, EDX
52195 JZ @@exit
52196 PUSH EBX
52197 PUSH EAX
52198 PUSH EDX
52199 PUSH ECX
52200 PUSH 0
52201 CALL GetDC
52202 PUSH EAX
52203 XCHG EBX, EAX
52204 CALL CreateCompatibleBitmap
52205 POP EDX
52206 MOV [EDX].TBitmap.fHandle, EAX
52207 PUSH EBX
52208 PUSH 0
52209 CALL ReleaseDC
52210 POP EBX
52211 @@exit: POP EAX
52212 end;
52213 {$ELSE ASM_VERSION} //Pascal
52214 function NewBitmap( W, H: Integer ): PBitmap;
52215 var DC: HDC;
52216 begin
52218 New( Result, Create );
52219 {+}{++}(*Result := PBitmap.Create;*){--}
52220 Result.fHandleType := bmDDB;
52221 Result.fDetachCanvas := DummyDetachCanvas;
52222 Result.fWidth := W;
52223 Result.fHeight := H;
52224 if (W <> 0) and (H <> 0) then
52225 begin
52226 //DC := CreateCompatibleDC( 0 );
52227 DC := GetDC( 0 );
52228 Result.fHandle := CreateCompatibleBitmap( DC, W, H );
52229 Assert( Result.fHandle <> 0, 'Can not create bitmap handle' );
52230 //DeleteDC( DC );
52231 ReleaseDC( 0, DC );
52232 end;
52233 end;
52234 {$ENDIF ASM_VERSION}
52235 //[END NewBitmap]
52237 const InitColors: array[ 0..17 ] of DWORD = ( $F800, $7E0, $1F, 0, $800000, $8000,
52238 $808000, $80, $800080, $8080, $808080, $C0C0C0, $FF0000, $FF00, $FFFF00, $FF,
52239 $FF00FF, $FFFF );
52240 //[PROCEDURE PreparePF16bit]
52241 {$IFDEF ASM_VERSION}
52242 procedure PreparePF16bit( DIBHeader: PBitmapInfo );
52243 const szBIH = sizeof(TBitmapInfoHeader);
52245 MOV byte ptr [EAX].TBitmapInfoHeader.biCompression, BI_BITFIELDS
52246 ADD EAX, szBIH
52247 XCHG EDX, EAX
52248 MOV EAX, offset[InitColors]
52249 XOR ECX, ECX
52250 MOV CL, 19*4
52251 CALL System.Move
52252 end;
52253 {$ELSE ASM_VERSION} //Pascal
52254 procedure PreparePF16bit( DIBHeader: PBitmapInfo );
52255 begin
52256 DIBHeader.bmiHeader.biCompression := BI_BITFIELDS;
52257 Move( InitColors[ 0 ], DIBHeader.bmiColors[ 0 ], 19*Sizeof(TRGBQUAD) );
52258 end;
52259 {$ENDIF ASM_VERSION}
52260 //[END PreparePF16bit]
52262 //[FUNCTION NewDIBBitmap]
52263 {$IFDEF ASM_VERSION}
52264 function NewDIBBitmap( W, H: Integer; PixelFormat: TPixelFormat ): PBitmap;
52266 PUSH EBX
52268 PUSH ECX
52269 PUSH EDX
52270 PUSH EAX
52271 CALL _NewBitmap
52272 XCHG EBX, EAX
52273 POP EAX //W
52274 POP EDX //H
52275 POP ECX //PixelFormat
52277 TEST EAX, EAX
52278 JZ @@exit
52279 TEST EDX, EDX
52280 JZ @@exit
52282 PUSH EAX
52283 MOVZX EAX, CL
52284 JMP @@loadBitsPixel
52285 @@loadDefault:
52286 MOVZX EAX, [DefaultPixelFormat]
52287 @@loadBitsPixel:
52288 MOVZX ECX, byte ptr [ BitsPerPixel_By_PixelFormat + EAX ]
52289 JECXZ @@loadDefault
52290 MOV [EBX].TBitmap.fNewPixelFormat, AL
52291 {$IFDEF PARANOIA}
52292 DB $3C, pf16bit
52293 {$ELSE}
52294 CMP AL, pf16bit
52295 {$ENDIF}
52296 POP EAX
52298 PUSHFD
52299 CALL PrepareBitmapHeader
52300 MOV [EBX].TBitmap.fDIBHeader, EAX
52301 POPFD
52302 JNZ @@2
52304 CALL PreparePF16bit
52306 @@2:
52307 MOV EAX, EBX
52308 CALL TBitmap.GetScanLineSize
52309 MOV EDX, [EBX].TBitmap.fHeight
52310 MUL EDX
52311 MOV [EBX].TBitmap.fDIBSize, EAX
52312 CALL AllocMem
52313 MOV [EBX].TBitmap.fDIBBits, EAX
52314 @@exit:
52315 XCHG EAX, EBX
52316 POP EBX
52317 end;
52318 {$ELSE ASM_VERSION} //Pascal
52319 function NewDIBBitmap( W, H: Integer; PixelFormat: TPixelFormat ): PBitmap;
52320 const BitsPerPixel: array[ TPixelFormat ] of Byte = ( 0, 1, 4, 8, 16, 16, 24, 32, 0 );
52321 var BitsPixel: Integer;
52322 //AField: PDWORD;
52323 //DC0 : HDC;
52324 begin
52326 New( Result, Create );
52327 {+}{++}(*Result := PBitmap.Create;*){--}
52328 Result.fDetachCanvas := DummyDetachCanvas;
52329 Result.fWidth := W;
52330 Result.fHeight := H;
52331 if (W <> 0) and (H <> 0) then
52332 begin
52333 BitsPixel := BitsPerPixel[ PixelFormat ];
52334 if BitsPixel = 0 then
52335 begin
52336 Result.fNewPixelFormat := DefaultPixelFormat;
52337 BitsPixel := BitsPerPixel[DefaultPixelFormat];
52339 else
52340 Result.fNewPixelFormat := PixelFormat;
52341 ASSERT( Result.fNewPixelFormat in [ pf1bit..pf32bit ], 'Strange pixel format' );
52342 Result.fDIBHeader := PrepareBitmapHeader( W, H, BitsPixel );
52343 if PixelFormat = pf16bit then
52344 begin
52345 PreparePF16bit( Result.fDIBHeader );
52347 Result.fDIBHeader.bmiHeader.biCompression := BI_BITFIELDS;
52348 AField := @Result.fDIBHeader.bmiColors[ 0 ];
52349 AField^ := $F800; Inc( AField );
52350 AField^ := $07E0; Inc( AField );
52351 AField^ := $001F; Inc( AField );
52352 DC0 := CreateCompatibleDC( 0 );
52353 GetSystemPaletteEntries( DC0, 0, 16, AField^ );
52354 DeleteDC( DC0 );
52356 end;
52358 Result.fDIBSize := Result.ScanLineSize * H;
52359 Result.fDIBBits := AllocMem( Result.fDIBSize );
52360 ASSERT( Result.fDIBBits <> nil, 'No memory' );
52361 end;
52362 end;
52363 {$ENDIF ASM_VERSION}
52364 //[END NewDIBBitmap]
52366 { TBitmap }
52368 {$IFDEF ASM_VERSION}
52369 //[procedure TBitmap.ClearData]
52370 procedure TBitmap.ClearData;
52372 PUSH EBX
52373 MOV EBX, EAX
52374 CALL [EBX].fDetachCanvas
52375 XOR ECX, ECX
52376 XCHG ECX, [EBX].fHandle
52377 JECXZ @@1
52378 PUSH ECX
52379 CALL DeleteObject
52380 XOR ECX, ECX
52381 MOV [EBX].fDIBBits, ECX
52382 @@1: XCHG ECX, [EBX].fDIBBits
52383 JECXZ @@2
52384 XCHG EAX, ECX
52385 CALL System.@FreeMem
52386 @@2: XOR ECX, ECX
52387 XCHG ECX, [EBX].fDIBHeader
52388 JECXZ @@3
52389 XCHG EAX, ECX
52390 CALL System.@FreeMem
52391 @@3: XOR EAX, EAX
52392 MOV [EBX].fScanLineSize, EAX
52393 MOV [EBX].fGetDIBPixels, EAX
52394 MOV [EBX].fSetDIBPixels, EAX
52395 XCHG EAX, EBX
52396 POP EBX
52397 CALL ClearTransImage
52398 end;
52399 {$ELSE ASM_VERSION} //Pascal
52400 procedure TBitmap.ClearData;
52401 begin
52402 fDetachCanvas( @Self );
52403 if fHandle <> 0 then
52404 begin
52405 DeleteObject( fHandle );
52406 fHandle := 0;
52407 fDIBBits := nil;
52408 //fDIBHeader := nil;
52409 end;
52410 if fDIBBits <> nil then
52411 begin
52412 FreeMem( fDIBBits );
52413 fDIBBits := nil;
52414 end;
52415 if fDIBHeader <> nil then
52416 begin
52417 FreeMem( fDIBHeader );
52418 fDIBHeader := nil;
52419 end;
52420 fScanLineSize := 0;
52421 fGetDIBPixels := nil;
52422 fSetDIBPixels := nil;
52423 ClearTransImage;
52424 end;
52425 {$ENDIF ASM_VERSION}
52427 {$IFDEF ASM_VERSION}
52428 //[procedure TBitmap.Clear]
52429 procedure TBitmap.Clear;
52431 PUSH EAX
52432 CALL RemoveCanvas
52433 POP EAX
52434 PUSH EAX
52435 CALL ClearData
52436 POP EAX
52437 XOR EDX, EDX
52438 MOV [EAX].fWidth, EDX
52439 MOV [EAX].fHeight, EDX
52440 MOV [EAX].fDIBAutoFree, DL
52441 end;
52442 {$ELSE ASM_VERSION} //Pascal
52443 procedure TBitmap.Clear;
52444 begin
52445 RemoveCanvas;
52446 ClearData;
52447 fWidth := 0;
52448 fHeight := 0;
52449 fDIBAutoFree := FALSE;
52450 end;
52451 {$ENDIF ASM_VERSION}
52453 //[function TBitmap.GetBoundsRect]
52454 function TBitmap.GetBoundsRect: TRect;
52455 begin
52456 Result := MakeRect( 0, 0, Width, Height );
52457 end;
52459 {$IFDEF ASM_VERSION}
52460 //[destructor TBitmap.Destroy]
52461 destructor TBitmap.Destroy;
52463 PUSH EAX
52464 CALL Clear
52465 POP EAX
52466 CALL TObj.Destroy
52467 end;
52468 {$ELSE ASM_VERSION} //Pascal
52469 destructor TBitmap.Destroy;
52470 begin
52471 Clear;
52472 inherited;
52473 end;
52474 {$ENDIF ASM_VERSION}
52476 //[function TBitmap.BitsPerPixel]
52477 function TBitmap.BitsPerPixel: Integer;
52478 var B: tagBitmap;
52479 begin
52480 CASE PixelFormat OF
52481 pf1bit: Result := 1;
52482 pf4bit: Result := 4;
52483 pf8bit: Result := 8;
52484 pf15bit: Result := 15;
52485 pf16bit: Result := 16;
52486 pf24bit: Result := 24;
52487 pf32bit: Result := 32;
52488 else begin
52489 Result := 0;
52490 if fHandle <> 0 then
52491 if GetObject( fHandle, Sizeof( B ), @B ) > 0 then
52492 Result := B.bmBitsPixel * B.bmPlanes;
52493 end;
52494 END;
52495 end;
52497 {$IFDEF ASM_VERSION}
52498 //[procedure TBitmap.Draw]
52499 procedure TBitmap.Draw(DC: HDC; X, Y: Integer);
52500 const szBitmap = sizeof( tagBitmap );
52501 asm // [EBP+8] = Y
52502 PUSH EDX // [EBP-4] = DC
52503 PUSH ECX // [EBP-8] = X
52504 PUSH EBX
52505 PUSH ESI
52506 @@try_again:
52507 MOV EBX, EAX
52508 CALL GetEmpty // GetEmpty must be assembler version !
52509 JZ @@exit
52511 MOV ECX, [EBX].fHandle
52512 JECXZ @@2
52514 //MOV EAX, EBX
52515 //CALL [EBX].fDetachCanvas // detached in StartDC
52517 ADD ESP, -szBitmap
52518 PUSH ESP
52519 PUSH szBitmap
52520 PUSH [EBX].fHandle
52521 CALL GetObject
52522 TEST EAX, EAX
52523 MOV ESI, [ESP].tagBitmap.bmHeight
52524 {$IFDEF USE_CMOV}
52525 CMOVZ ESI, [EBX].fHeight
52526 {$ELSE}
52527 JNZ @@1
52528 MOV ESI, [EBX].fHeight
52529 @@1: {$ENDIF}
52531 ADD ESP, szBitmap
52532 CALL StartDC
52534 PUSH SRCCOPY
52535 PUSH 0
52536 PUSH 0
52537 PUSH EAX
52538 CALL @@prepare
52539 CALL BitBlt
52540 CALL FinishDC
52541 JMP @@exit
52543 @@prepare:
52544 XCHG ESI, [ESP]
52545 PUSH [EBX].fWidth
52546 PUSH Y
52547 PUSH dword ptr [EBP-8]
52548 PUSH dword ptr [EBP-4]
52549 JMP ESI
52551 @@2:
52552 MOV ECX, [EBX].fDIBHeader
52553 JECXZ @@exit
52555 MOV ESI, [ECX].TBitmapInfoHeader.biHeight
52556 TEST ESI, ESI
52557 JGE @@20
52558 NEG ESI
52559 @@20:
52560 PUSH SRCCOPY
52561 PUSH DIB_RGB_COLORS
52562 PUSH ECX
52563 PUSH [EBX].fDIBBits
52564 PUSH ESI
52565 PUSH [EBX].fWidth
52566 PUSH 0
52567 PUSH 0
52568 CALL @@prepare
52569 CALL StretchDIBits
52570 TEST EAX, EAX
52571 JNZ @@exit
52572 MOV EAX, EBX
52573 CALL GetHandle
52574 TEST EAX, EAX
52575 XCHG EAX, EBX
52576 JNZ @@try_again
52577 @@exit:
52578 POP ESI
52579 POP EBX
52580 MOV ESP, EBP
52581 end;
52582 {$ELSE ASM_VERSION} //Pascal
52583 procedure TBitmap.Draw(DC: HDC; X, Y: Integer);
52585 DCfrom, DC0: HDC;
52586 oldBmp: HBitmap;
52587 oldHeight: Integer;
52588 B: tagBitmap;
52589 label
52590 TRYAgain;
52591 begin
52592 TRYAgain:
52593 if Empty then Exit;
52594 if fHandle <> 0 then
52595 begin
52596 fDetachCanvas( @Self );
52597 oldHeight := fHeight;
52598 if GetObject( fHandle, sizeof( B ), @B ) <> 0 then
52599 oldHeight := B.bmHeight;
52600 ASSERT( oldHeight > 0, 'oldHeight must be > 0' );
52602 DC0 := GetDC( 0 );
52603 DCfrom := CreateCompatibleDC( DC0 );
52604 ReleaseDC( 0, DC0 );
52606 oldBmp := SelectObject( DCfrom, fHandle );
52607 ASSERT( oldBmp <> 0, 'Can not select bitmap to DC' );
52609 BitBlt( DC, X, Y, fWidth, oldHeight, DCfrom, 0, 0, SRCCOPY );
52610 {$IFDEF CHK_BITBLT} Chk_BitBlt; {$ENDIF}
52612 SelectObject( DCfrom, oldBmp );
52613 DeleteDC( DCfrom );
52615 else
52616 if fDIBBits <> nil then
52617 begin
52618 oldHeight := Abs(fDIBHeader.bmiHeader.biHeight);
52619 ASSERT( oldHeight > 0, 'oldHeight must be > 0' );
52620 ASSERT( fWidth > 0, 'Width must be > 0' );
52621 if StretchDIBits( DC, X, Y, fWidth, oldHeight, 0, 0, fWidth, oldHeight,
52622 fDIBBits, fDIBHeader^, DIB_RGB_COLORS, SRCCOPY ) = 0 then
52623 begin
52624 if GetHandle <> 0 then
52625 goto TRYAgain;
52626 end;
52627 end;
52628 end;
52629 {$ENDIF ASM_VERSION}
52631 {$IFDEF ASM_VERSION}
52632 //[procedure TBitmap.StretchDraw]
52633 procedure TBitmap.StretchDraw(DC: HDC; const Rect: TRect);
52635 PUSH EBX
52636 PUSH EDI
52637 PUSH EBP
52638 MOV EBP, ESP
52639 PUSH EDX
52640 PUSH ECX
52641 MOV EBX, EAX
52642 CALL GetEmpty
52643 JZ @@exit
52645 MOV ECX, [EBX].fHandle
52646 JECXZ @@2
52648 @@0:
52649 CALL StartDC
52650 PUSH SRCCOPY
52651 PUSH [EBX].fHeight
52652 PUSH [EBX].fWidth
52653 PUSH 0
52654 PUSH 0
52655 PUSH EAX
52657 CALL @@prepare
52658 CALL StretchBlt
52659 CALL FinishDC
52660 JMP @@exit
52662 @@prepare:
52663 POP EDI
52664 MOV EAX, [EBP-8]
52665 MOV EDX, [EAX].TRect.Bottom
52666 MOV ECX, [EAX].TRect.Top
52667 SUB EDX, ECX
52668 PUSH EDX
52669 MOV EDX, [EAX].TRect.Right
52670 MOV EAX, [EAX].TRect.Left
52671 SUB EDX, EAX
52672 PUSH EDX
52673 PUSH ECX
52674 PUSH EAX
52675 PUSH dword ptr [EBP-4]
52676 JMP EDI
52679 @@2: MOV ECX, [EBX].fDIBHeader
52680 JECXZ @@exit
52682 PUSH SRCCOPY
52683 PUSH DIB_RGB_COLORS
52684 PUSH ECX
52685 PUSH [EBX].fDIBBits
52686 PUSH [EBX].fHeight
52687 PUSH [EBX].fWidth
52688 PUSH 0
52689 PUSH 0
52690 CALL @@prepare
52691 CALL StretchDIBits
52692 TEST EAX, EAX
52693 JG @@exit
52695 MOV EAX, EBX
52696 CALL GetHandle
52697 MOV ECX, [EBX].fHandle
52698 JECXZ @@exit
52699 JMP @@0
52701 @@exit: MOV ESP, EBP
52702 POP EBP
52703 POP EDI
52704 POP EBX
52705 end;
52706 {$ELSE ASM_VERSION} //Pascal
52707 procedure TBitmap.StretchDraw(DC: HDC; const Rect: TRect);
52708 var DCfrom: HDC;
52709 oldBmp: HBitmap;
52710 label DrawHandle;
52711 begin
52712 if Empty then Exit;
52713 DrawHandle:
52714 if fHandle <> 0 then
52715 begin
52716 fDetachCanvas( @Self );
52717 DCfrom := CreateCompatibleDC( 0 );
52718 oldBmp := SelectObject( DCfrom, fHandle );
52719 ASSERT( oldBmp <> 0, 'Can not select bitmap to DC' );
52720 StretchBlt( DC, Rect.Left, Rect.Top, Rect.Right - Rect.Left,
52721 Rect.Bottom - Rect.Top, DCfrom, 0, 0, fWidth, fHeight,
52722 SRCCOPY );
52723 SelectObject( DCfrom, oldBmp );
52724 DeleteDC( DCfrom );
52726 else
52727 if fDIBBits <> nil then
52728 begin
52729 if StretchDIBits( DC, Rect.Left, Rect.Top, Rect.Right - Rect.Left,
52730 Rect.Bottom - Rect.Top, 0, 0, fWidth, fHeight,
52731 fDIBBits, fDIBHeader^, DIB_RGB_COLORS, SRCCOPY )<=0 then
52732 begin
52733 if GetHandle <> 0 then
52734 goto DrawHandle;
52735 end;
52736 end;
52737 end;
52738 {$ENDIF ASM_VERSION}
52740 //[procedure TBitmap.DrawMasked]
52741 procedure TBitmap.DrawMasked(DC: HDC; X, Y: Integer; Mask: HBitmap);
52742 begin
52743 StretchDrawMasked( DC, MakeRect( X, Y, X + fWidth, Y + fHeight ), Mask );
52744 end;
52746 {$IFDEF ASM_VERSION}
52747 //[procedure TBitmap.DrawTransparent]
52748 procedure TBitmap.DrawTransparent(DC: HDC; X, Y: Integer; TranspColor: TColor);
52750 PUSH ECX
52751 MOV ECX, TranspColor
52752 INC ECX
52753 MOV ECX, [Y]
52754 JNZ @@2
52755 XCHG ECX, [ESP]
52756 CALL Draw
52757 JMP @@exit
52758 @@2:
52759 ADD ECX, [EAX].fHeight
52760 PUSH ECX
52761 MOV ECX, [EBP-4]
52762 ADD ECX, [EAX].fWidth
52763 PUSH ECX
52764 PUSH [Y]
52765 PUSH dword ptr [EBP-4]
52766 MOV ECX, ESP
52767 PUSH [TranspColor]
52768 CALL StretchDrawTransparent
52769 @@exit:
52770 MOV ESP, EBP
52771 end;
52772 {$ELSE ASM_VERSION} //Pascal
52773 procedure TBitmap.DrawTransparent(DC: HDC; X, Y: Integer; TranspColor: TColor);
52774 begin
52775 if TranspColor = clNone then
52776 Draw( DC, X, Y )
52777 else
52778 StretchDrawTransparent( DC, MakeRect( X, Y, X + fWidth, Y + fHeight ),
52779 TranspColor );
52780 end;
52781 {$ENDIF ASM_VERSION}
52783 {$IFDEF ASM_VERSION}
52784 //[procedure TBitmap.StretchDrawTransparent]
52785 procedure TBitmap.StretchDrawTransparent(DC: HDC; const Rect: TRect; TranspColor: TColor);
52787 PUSH EBX
52788 XCHG EBX, EAX
52789 MOV EAX, [TranspColor]
52790 INC EAX
52791 MOV EAX, EBX
52792 JNZ @@2
52793 CALL StretchDraw
52794 JMP @@exit
52795 @@2:
52796 PUSH EDX
52797 PUSH ECX
52798 CALL GetHandle
52799 TEST EAX, EAX
52800 JZ @@exit2
52802 MOV EAX, [TranspColor]
52803 CALL Color2RGB
52804 MOV ECX, [EBX].fTransMaskBmp
52805 JECXZ @@makemask0
52806 CMP EAX, [EBX].fTransColor
52807 JE @@3
52808 @@makemask0:
52809 MOV [EBX].fTransColor, EAX
52810 INC ECX
52811 LOOP @@20
52812 //MOV EAX, [EBX].fWidth
52813 //MOV EDX, [EBX].fHeight
52814 XOR EAX, EAX // pass height = 0
52815 // absolutely no matter what to pass as width
52816 CALL NewBitmap
52817 MOV [EBX].fTransMaskBmp, EAX
52818 @@20:
52819 MOV EAX, [EBX].fTransMaskBmp
52820 PUSH EAX
52821 MOV EDX, EBX
52822 CALL Assign
52823 POP EAX
52824 MOV EDX, [EBX].fTransColor
52825 CALL Convert2Mask
52826 @@3:
52827 MOV EAX, [EBX].fTransMaskBmp
52828 CALL GetHandle
52829 POP ECX
52830 POP EDX
52831 PUSH EAX
52832 XCHG EAX, EBX
52833 CALL StretchDrawMasked
52834 JMP @@exit
52835 @@exit2:
52836 POP ECX
52837 POP EDX
52838 @@exit:
52839 POP EBX
52840 end;
52841 {$ELSE ASM_VERSION} //Pascal
52842 procedure TBitmap.StretchDrawTransparent(DC: HDC; const Rect: TRect; TranspColor: TColor);
52843 begin
52844 if TranspColor = clNone then
52845 StretchDraw( DC, Rect )
52846 else
52847 begin
52848 if GetHandle = 0 then Exit;
52849 TranspColor := Color2RGB( TranspColor );
52850 if (fTransMaskBmp = nil) or (fTransColor <> TranspColor) then
52851 begin
52852 if fTransMaskBmp = nil then
52853 fTransMaskBmp := NewBitmap( 0, 0 {fWidth, fHeight} );
52854 fTransColor := TranspColor;
52855 // Create here mask bitmap:
52856 fTransMaskBmp.Assign( @Self );
52857 fTransMaskBmp.Convert2Mask( TranspColor );
52858 end;
52859 StretchDrawMasked( DC, Rect, fTransMaskBmp.Handle );
52860 end;
52861 end;
52862 {$ENDIF ASM_VERSION}
52864 const
52865 ROP_DstCopy = $00AA0029;
52866 {$IFDEF ASM_VERSION}
52867 //[procedure TBitmap.StretchDrawMasked]
52868 procedure TBitmap.StretchDrawMasked(DC: HDC; const Rect: TRect; Mask: HBitmap);
52870 PUSH EDX // [EBP-4] = DC
52871 PUSH ECX // [EBP-8] = Rect
52872 PUSH EBX // save EBX
52873 MOV EBX, EAX
52874 PUSH ESI // save ESI
52875 CALL GetHandle
52876 TEST EAX, EAX
52877 JZ @@to_exit
52879 PUSH 0
52880 CALL CreateCompatibleDC
52881 PUSH EAX // [EBP-20] = MaskDC
52883 PUSH [Mask]
52884 PUSH EAX
52885 CALL SelectObject
52886 PUSH EAX // [EBP-24] = Save4Mask
52888 CALL StartDC // [EBP-28] = DCfrom; [EBP-32] = Save4From
52890 PUSH [EBX].fHeight
52891 PUSH [EBX].fWidth
52892 PUSH EAX
52893 CALL CreateCompatibleBitmap
52894 PUSH EAX // [EBP-36] = MemBmp
52896 PUSH 0
52897 CALL CreateCompatibleDC
52898 PUSH EAX // [EBP-40] = MemDC
52900 PUSH dword ptr [EBP-36] //MemBmp
52901 PUSH EAX
52902 CALL SelectObject
52903 PUSH EAX // [EBP-44] = Save4Mem
52905 PUSH SRCCOPY
52906 MOV EAX, [EBP-20] //MaskDC
52907 CALL @@stretch1
52909 PUSH SRCERASE
52910 MOV EAX, [EBP-28] //DCfrom
52911 CALL @@stretch1
52913 PUSH 0
52914 PUSH dword ptr [EBP-4] //DC
52915 CALL SetTextColor
52916 PUSH EAX // [EBP-48] = crText
52918 PUSH $FFFFFF
52919 PUSH dword ptr [EBP-4] //DC
52920 CALL Windows.SetBkColor
52921 PUSH EAX // [EBP-52] = crBack
52923 PUSH SRCAND
52924 MOV EAX, [EBP-20] //MaskDC
52925 CALL @@stretch2
52927 PUSH SRCINVERT
52928 MOV EAX, [EBP-40] //MemDC
52929 CALL @@stretch2
52931 PUSH dword ptr [EBP-4] //DC
52932 CALL Windows.SetBkColor
52934 PUSH dword ptr [EBP-4] //DC
52935 CALL SetTextColor
52937 MOV ESI, offset[FinishDC]
52938 CALL ESI
52939 CALL DeleteObject // DeleteObject( MemBmp )
52941 CALL ESI
52943 CALL ESI
52944 @@to_exit:
52946 JC @@exit
52948 @@stretch1:
52949 POP ESI
52950 PUSH [EBX].fHeight
52951 PUSH [EBX].fWidth
52952 XOR EDX, EDX
52953 PUSH EDX
52954 PUSH EDX
52955 PUSH EAX
52956 PUSH [EBX].fHeight
52957 PUSH [EBX].fWidth
52958 PUSH EDX
52959 PUSH EDX
52960 PUSH dword ptr [EBP-40] //MemDC
52961 JMP @@stretch3
52963 @@stretch2:
52964 POP ESI
52965 PUSH [EBX].fHeight
52966 PUSH [EBX].fWidth
52967 PUSH 0
52968 PUSH 0
52969 PUSH EAX
52970 MOV EAX, [EBP-8] //Rect
52971 MOV EDX, [EAX].TRect.Bottom
52972 MOV ECX, [EAX].TRect.Top
52973 SUB EDX, ECX
52974 PUSH EDX
52975 MOV EDX, [EAX].TRect.Right
52976 MOV EAX, [EAX].TRect.Left
52977 SUB EDX, EAX
52978 PUSH EDX
52979 PUSH ECX
52980 PUSH EAX
52981 PUSH dword ptr [EBP-4] //DC
52982 @@stretch3:
52983 CALL StretchBlt
52984 JMP ESI
52986 @@exit:
52987 POP ESI
52988 POP EBX
52989 MOV ESP, EBP
52990 end;
52991 {$ELSE ASM_VERSION} //Pascal
52992 procedure TBitmap.StretchDrawMasked(DC: HDC; const Rect: TRect; Mask: HBitmap);
52994 DCfrom, MemDC, MaskDC: HDC;
52995 MemBmp: HBITMAP;
52996 Save4From, Save4Mem, Save4Mask: THandle;
52997 crText, crBack: TColorRef;
52998 //SavePal: HPALETTE;
52999 begin
53000 if GetHandle = 0 then Exit;
53001 fDetachCanvas( @Self );
53002 //SavePal := 0;
53004 DCfrom := CreateCompatibleDC( 0 );
53005 Save4From := SelectObject( DCfrom, fHandle );
53006 ASSERT( Save4From <> 0, 'Can not select source bitmap to DC' );
53007 MaskDC := CreateCompatibleDC( 0 );
53008 Save4Mask := SelectObject( MaskDC, Mask );
53009 ASSERT( Save4Mask <> 0, 'Can not select mask bitmap to DC' );
53010 MemDC := CreateCompatibleDC( 0 );
53011 //try
53012 MemBmp := CreateCompatibleBitmap( DCfrom, fWidth, fHeight );
53013 Save4Mem := SelectObject( MemDC, MemBmp );
53014 ASSERT( Save4Mem <> 0, 'Can not select memory bitmap to DC' );
53015 //SavePal := SelectPalette(DCfrom, SystemPalette16, False);
53016 //SelectPalette(DCfrom, SavePal, False);
53017 //if SavePal <> 0 then
53018 // SavePal := SelectPalette(MemDC, SavePal, True)
53019 //else
53020 // SavePal := SelectPalette(MemDC, SystemPalette16, True);
53021 //RealizePalette(MemDC);
53023 StretchBlt( MemDC, 0, 0, fWidth, fHeight, MaskDC, 0, 0, fWidth, fHeight, SrcCopy);
53024 StretchBlt( MemDC, 0, 0, fWidth, fHeight, DCfrom, 0, 0, fWidth, fHeight, SrcErase);
53025 crText := SetTextColor(DC, $0);
53026 crBack := Windows.SetBkColor(DC, $FFFFFF);
53027 StretchBlt( DC, Rect.Left, Rect.Top, Rect.Right - Rect.Left, Rect.Bottom - Rect.Top,
53028 MaskDC, 0, 0, fWidth, fHeight, SrcAnd);
53029 StretchBlt( DC, Rect.Left, Rect.Top, Rect.Right - Rect.Left, Rect.Bottom - Rect.Top,
53030 MemDC, 0, 0, fWidth, fHeight, SrcInvert);
53031 Windows.SetBkColor( DC, crBack);
53032 SetTextColor( DC, crText);
53034 if Save4Mem <> 0 then
53035 SelectObject( MemDC, Save4Mem );
53036 DeleteObject(MemBmp);
53037 //finally
53038 //if SavePal <> 0 then SelectPalette(MemDC, SavePal, False);
53039 DeleteDC(MemDC);
53040 SelectObject( DCfrom, Save4From );
53041 DeleteDC( DCfrom );
53042 SelectObject( MaskDC, Save4Mask );
53043 DeleteDC( MaskDC );
53044 //end;
53045 end;
53046 {$ENDIF ASM_VERSION}
53048 //[procedure ApplyBitmapBkColor2Canvas]
53049 procedure ApplyBitmapBkColor2Canvas( Sender: PBitmap );
53050 begin
53051 if Sender.fCanvas = nil then Exit;
53052 Sender.fCanvas.Brush.Color := Sender.BkColor;
53053 end;
53055 //[PROCEDURE DetachBitmapFromCanvas]
53056 {$IFDEF ASM_VERSION}
53057 procedure DetachBitmapFromCanvas( Sender: PBitmap );
53059 XOR ECX, ECX
53060 XCHG ECX, [EAX].TBitmap.fCanvasAttached
53061 JECXZ @@exit
53062 PUSH ECX
53063 MOV EAX, [EAX].TBitmap.fCanvas
53064 PUSH [EAX].TCanvas.fHandle
53065 CALL SelectObject
53066 @@exit:
53067 end;
53068 {$ELSE ASM_VERSION} //Pascal
53069 procedure DetachBitmapFromCanvas( Sender: PBitmap );
53070 begin
53071 if Sender.fCanvasAttached = 0 then Exit;
53072 SelectObject( Sender.fCanvas.fHandle, Sender.fCanvasAttached );
53073 Sender.fCanvasAttached := 0;
53074 end;
53075 {$ENDIF ASM_VERSION}
53076 //[END DetachBitmapFromCanvas]
53078 {$IFDEF ASM_VERSION}
53079 //[function TBitmap.GetCanvas]
53080 function TBitmap.GetCanvas: PCanvas;
53082 PUSH EBX
53083 MOV EBX, EAX
53084 CALL GetEmpty
53085 JZ @@exit
53086 MOV EAX, EBX
53087 CALL GetHandle
53088 TEST EAX, EAX
53089 JZ @@exit
53090 MOV ECX, [EBX].fCanvas
53091 INC ECX
53092 LOOP @@ret_Canvas
53094 MOV [EBX].fApplyBkColor2Canvas, offset[ApplyBitmapBkColor2Canvas]
53095 PUSH 0
53096 CALL CreateCompatibleDC
53097 CALL NewCanvas
53098 MOV [EBX].fCanvas, EAX
53099 MOV [EAX].TCanvas.fOnChange.TMethod.Code, offset[CanvasChanged]
53100 MOV [EAX].TCanvas.fOnChange.TMethod.Data, EBX
53101 CALL TCanvas.GetBrush
53102 XOR EDX, EDX
53103 MOV ECX, [EBX].fBkColor
53104 CALL TGraphicTool.SetInt
53106 @@ret_Canvas:
53107 MOV EAX, [EBX].fCanvas
53108 MOV ECX, [EAX].TCanvas.fHandle
53109 INC ECX
53110 LOOP @@attach_Canvas
53111 PUSH EAX
53112 MOV [EBX].fCanvasAttached, ECX
53113 PUSH ECX
53114 CALL CreateCompatibleDC
53115 XCHG EDX, EAX
53116 POP EAX
53117 CALL TCanvas.SetHandle
53119 @@attach_Canvas:
53120 MOV ECX, [EBX].fCanvasAttached
53121 INC ECX
53122 LOOP @@2
53123 PUSH [EBX].fHandle
53124 MOV EAX, [EBX].fCanvas
53125 CALL TCanvas.GetHandle
53126 PUSH EAX
53127 CALL SelectObject
53128 MOV [EBX].fCanvasAttached, EAX
53130 @@2: MOV [EBX].fDetachCanvas, offset[DetachBitmapFromCanvas]
53131 MOV EAX, [EBX].fCanvas
53132 @@exit: POP EBX
53133 end;
53134 {$ELSE ASM_VERSION} //Pascal
53135 function TBitmap.GetCanvas: PCanvas;
53136 var DC: HDC;
53137 begin
53138 Result := nil;
53139 if Empty then Exit;
53140 if GetHandle = 0 then Exit;
53141 if fCanvas = nil then
53142 begin
53143 fApplyBkColor2Canvas := ApplyBitmapBkColor2Canvas;
53144 DC := CreateCompatibleDC( 0 );
53145 fCanvas := NewCanvas( DC );
53146 fCanvas.fIsPaintDC := FALSE;
53147 fCanvas.OnChange := CanvasChanged;
53148 fCanvas.Brush.Color := fBkColor;
53149 end;
53150 Result := fCanvas;
53152 if fCanvas.fHandle = 0 then
53153 begin
53154 DC := CreateCompatibleDC( 0 );
53155 fCanvas.Handle := DC;
53156 fCanvasAttached := 0;
53157 end;
53159 if fCanvasAttached = 0 then
53160 begin
53161 fCanvasAttached := SelectObject( fCanvas.Handle, fHandle );
53162 ASSERT( fCanvasAttached <> 0, 'Can not select bitmap to DC of Canvas' );
53163 end;
53164 fDetachCanvas := DetachBitmapFromCanvas;
53165 end;
53166 {$ENDIF ASM_VERSION}
53168 {$IFDEF ASM_VERSION}
53169 //[function TBitmap.GetEmpty]
53170 function TBitmap.GetEmpty: Boolean;
53172 PUSH ECX
53173 MOV ECX, [EAX].fWidth
53174 JECXZ @@1
53175 MOV ECX, [EAX].fHeight
53176 @@1: TEST ECX, ECX
53177 POP ECX
53178 SETZ AL
53179 end;
53180 {$ELSE ASM_VERSION} //Pascal
53181 function TBitmap.GetEmpty: Boolean;
53182 begin
53183 Result := (fWidth = 0) or (fHeight = 0);
53184 ASSERT( (fWidth >= 0) and (fHeight >= 0), 'Bitmap dimensions can be negative' );
53185 end;
53186 {$ENDIF ASM_VERSION}
53188 {$IFDEF ASM_noVERSION}
53189 //[function TBitmap.GetHandle]
53190 function TBitmap.GetHandle: HBitmap;
53192 PUSH EBX
53193 MOV EBX, EAX
53194 CALL GetEmpty
53195 JZ @@exit
53196 MOV ECX, [EBX].fHandle
53197 INC ECX
53198 LOOP @@exit
53200 MOV ECX, [EBX].fDIBBits
53201 JECXZ @@exit
53203 PUSH ECX
53204 PUSH 0
53205 CALL GetDC
53206 PUSH EAX
53207 PUSH 0
53208 PUSH 0
53209 LEA EDX, [EBX].fDIBBits
53210 PUSH EDX
53211 PUSH DIB_RGB_COLORS
53212 PUSH [EBX].fDIBHeader
53213 PUSH EAX
53214 CALL CreateDIBSection
53215 MOV [EBX].fHandle, EAX
53216 PUSH 0
53217 CALL ReleaseDC
53218 POP EAX
53219 PUSH EAX
53220 MOV EDX, [EBX].fDIBBits
53221 MOV ECX, [EBX].fDIBSize
53222 CALL System.Move
53223 POP EAX
53224 CMP [EBX].fDIBAutoFree, 0
53225 JNZ @@freed
53226 CALL System.@FreeMem
53227 @@freed:MOV [EBX].fDIBAutoFree, 1
53228 XOR EAX, EAX
53229 MOV [EBX].fGetDIBPixels, EAX
53230 MOV [EBX].fSetDIBPixels, EAX
53232 @@exit: MOV EAX, [EBX].fHandle
53233 POP EBX
53234 end;
53235 {$ELSE ASM_VERSION} //Pascal
53236 function TBitmap.GetHandle: HBitmap;
53237 var OldBits: Pointer;
53238 DC0: HDC;
53239 {$IFDEF DEBUG}
53240 B: tagBitmap;
53241 {$ENDIF}
53242 begin
53243 Result := 0;
53244 if Empty then Exit;
53245 if fHandle = 0 then
53246 begin
53247 if fDIBBits <> nil then
53248 begin
53249 OldBits := fDIBBits;
53250 DC0 := GetDC( 0 );
53252 fDIBBits := nil;
53253 //fDIBHeader.bmiHeader.biCompression := 0;
53254 fHandle := CreateDIBSection( DC0, fDIBHeader^, DIB_RGB_COLORS,
53255 fDIBBits, 0, 0 );
53256 {$IFDEF DEBUG}
53257 if fHandle = 0 then
53258 ShowMessage( 'Can not create DIB section, error: ' + Int2Str( GetLastError ) +
53259 ', ' + SysErrorMessage( GetLastError ) );
53260 GetObject( fHandle, Sizeof( B ), @ B );
53261 {$ELSE}
53262 ASSERT( fHandle <> 0, 'Can not create DIB section, error: ' + Int2Str( GetLastError ) +
53263 ', ' + SysErrorMessage( GetLastError ) );
53264 {$ENDIF}
53265 ReleaseDC( 0, DC0 );
53266 if fHandle <> 0 then
53267 begin
53268 Move( OldBits^, fDIBBits^, fDIBSize );
53269 if not fDIBAutoFree then
53270 FreeMem( OldBits );
53271 fDIBAutoFree := TRUE;
53273 fGetDIBPixels := nil;
53274 fSetDIBPixels := nil;
53276 else
53277 fDIBBits := OldBits;
53278 end;
53279 end;
53280 Result := fHandle;
53281 end;
53282 {$ENDIF ASM_VERSION}
53284 //[function TBitmap.GetHandleAllocated]
53285 function TBitmap.GetHandleAllocated: Boolean;
53286 begin
53287 Result := fHandle <> 0;
53288 end;
53290 {$IFDEF ASM_VERSION}
53291 //[procedure TBitmap.LoadFromFile]
53292 procedure TBitmap.LoadFromFile(const Filename: String);
53294 PUSH EAX
53295 XCHG EAX, EDX
53296 CALL NewReadFileStream
53297 XCHG EDX, EAX
53298 POP EAX
53299 PUSH EDX
53300 CALL LoadFromStream
53301 POP EAX
53302 CALL TObj.Free
53303 end;
53304 {$ELSE ASM_VERSION} //Pascal
53305 procedure TBitmap.LoadFromFile(const Filename: String);
53306 var Strm: PStream;
53307 begin
53308 Strm := NewReadFileStream( Filename );
53309 LoadFromStream( Strm );
53310 Strm.Free;
53311 end;
53312 {$ENDIF ASM_VERSION}
53314 //[procedure TBitmap.LoadFromResourceID]
53315 procedure TBitmap.LoadFromResourceID(Inst: DWORD; ResID: Integer);
53316 begin
53317 LoadFromResourceName( Inst, MAKEINTRESOURCE( ResID ) );
53318 end;
53320 {$IFDEF ASM_VERSION}
53321 //[procedure TBitmap.LoadFromResourceName]
53322 procedure TBitmap.LoadFromResourceName(Inst: DWORD; ResName: PChar);
53324 PUSH EBX
53325 MOV EBX, EAX
53326 PUSHAD
53327 CALL Clear
53328 POPAD
53329 XOR EAX, EAX
53330 PUSH ECX
53331 MOVZX ECX, [EBX].fHandleType
53332 INC ECX
53333 LOOP @@1
53334 MOV AH, LR_CREATEDIBSECTION shr 8 // = $2000
53335 @@1: MOV AL, LR_DEFAULTSIZE // = $40
53336 POP ECX
53337 PUSH EAX
53338 PUSH 0
53339 PUSH 0
53340 PUSH IMAGE_BITMAP
53341 PUSH ECX
53342 PUSH EDX
53343 CALL LoadImage
53344 TEST EAX, EAX
53345 JZ @@exit
53346 XCHG EDX, EAX
53347 XCHG EAX, EBX
53348 CALL SetHandle
53349 @@exit: POP EBX
53350 end;
53351 {$ELSE ASM_VERSION} //Pascal
53352 procedure TBitmap.LoadFromResourceName(Inst: DWORD; ResName: PChar);
53353 var ResHandle: HBitmap;
53354 Flg: DWORD;
53355 begin
53356 Clear;
53357 //ResHandle := LoadBitmap( Inst, ResName );
53358 Flg := 0;
53359 if fHandleType = bmDIB then
53360 Flg := LR_CREATEDIBSECTION;
53361 ResHandle := LoadImage( Inst, ResName, IMAGE_BITMAP, 0, 0,
53362 LR_DEFAULTSIZE or Flg );
53363 if ResHandle = 0 then Exit;
53364 //Handle := CopyImage( ResHandle, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG );
53365 Handle := ResHandle;
53366 end;
53367 {$ENDIF ASM_VERSION}
53369 {$IFDEF F_P}
53370 type
53371 TBITMAPFILEHEADER = packed record
53372 bfType: Word;
53373 bfSize: DWORD;
53374 bfReserved1: Word;
53375 bfReserved2: Word;
53376 bfOffBits: DWORD;
53377 end;
53378 {$ENDIF}
53380 {$IFDEF ASM_noVERSION} // error + 16Colors->swap(Gray,Silver) + Core
53381 //[procedure TBitmap.LoadFromStream]
53382 procedure TBitmap.LoadFromStream(Strm: PStream);
53383 type tBFH = TBitmapFileHeader;
53384 tBIH = TBitmapInfoHeader;
53385 const szBIH = Sizeof( tBIH );
53386 szBFH = Sizeof( tBFH );
53388 PUSH EBX
53389 PUSH ESI
53390 MOV EBX, EAX
53391 PUSH EDX
53392 CALL Clear
53393 POP ESI
53394 MOV EAX, ESI
53395 CALL TStream.GetPosition
53396 PUSH EAX // [EBP+4] = Strm.Pos (starting pos)
53397 PUSH EBP
53398 MOV EBP, ESP
53399 ADD ESP, -(szBIH + szBFH)
53401 // reading bitmap
53402 XOR ECX, ECX
53403 MOV [EBX].fHandleType, CL
53404 MOV CL, szBFH
53405 MOV EDX, ESP
53406 PUSH ECX
53407 MOV EAX, ESI
53408 CALL TStream.Read
53409 POP ECX
53410 SUB ECX, EAX
53411 JNZ @@eread1
53413 CMP [ESP].tBFH.bfType, $4D42
53414 JE @@1
53415 MOV EDX, [EBP+4]
53416 MOV EAX, ESI
53417 CALL TStream.Seek
53418 XOR EAX, EAX
53419 XOR EDX, EDX
53420 JMP @@2
53422 @@1:
53423 MOV EDX, [ESP].tBFH.bfSize
53424 MOV EAX, [ESP].tBFH.bfOffBits
53425 @@2:
53426 PUSH EDX // Push Size
53427 PUSH EAX // Push Off
53428 XOR ECX, ECX
53429 MOV CL, szBIH
53430 LEA EDX, [EBP-szBIH]
53431 MOV EAX, ESI
53432 PUSH ECX
53433 CALL TStream.Read // read BIH
53434 POP ECX
53435 @@eread1:
53436 XOR ECX, EAX
53437 JNZ @@eread
53439 MOVZX EAX, [EBP-szBIH].tBIH.biBitCount
53440 MOVZX EDX, [EBP-szBIH].tBIH.biPlanes
53441 MUL EDX
53442 CALL Bits2PixelFormat
53443 {$IFDEF PARANOIA}
53444 DB $3C, pf15bit
53445 {$ELSE}
53446 CMP AL, pf15bit
53447 {$ENDIF}
53448 JNZ @@no15bit
53449 CMP [EBP-szBIH].tBIH.biCompression, 0
53450 JZ @@no15bit
53451 INC AL // AL = pf16bit
53452 @@no15bit:
53453 MOV [EBX].fNewPixelFormat, AL
53455 MOV EAX, szBIH + 1024
53456 CALL System.@GetMem
53457 MOV [EBX].fDIBHeader, EAX
53458 XCHG EDX, EAX
53459 LEA EAX, [EBP-szBIH]
53460 XOR ECX, ECX
53461 MOV CL, szBIH
53462 CALL System.Move
53464 MOV EAX, [EBP-szBIH].tBIH.biWidth
53465 MOV [EBX].fWidth, EAX
53466 MOV EAX, [EBP-szBIH].tBIH.biHeight
53467 TEST EAX, EAX
53468 JGE @@20
53469 NEG EAX
53470 @@20: MOV [EBX].fHeight, EAX
53472 MOV EAX, EBX
53473 CALL GetScanLineSize
53474 MOV EDX, [EBX].fHeight
53475 MUL EDX
53476 MOV [EBX].fDIBSize, EAX
53477 CALL AllocMem
53478 MOV [EBX].fDIBBits, EAX
53480 MOVZX EAX, [EBP-szBIH].tBIH.biBitCount
53481 {$IFDEF PARANOIA}
53482 DB $3C, 8
53483 {$ELSE}
53484 CMP AL, 8
53485 {$ENDIF}
53486 JA @@3
53487 MOV AL, 4
53488 MOVZX ECX, [EBP-szBIH].tBIH.biBitCount
53489 SAL EAX, CL
53490 XCHG ECX, EAX
53491 @@3:
53492 CMP [EBX].TBitmap.fNewPixelFormat, pf16bit
53493 JNE @@30
53494 XOR ECX, ECX
53495 MOV CL, 12 // ColorCount = 12
53496 @@30:
53497 POP EAX // EAX = off
53498 TEST EAX, EAX
53499 JLE @@4
53500 SUB EAX, szBFH + szBIH
53501 CMP EAX, ECX
53502 JZ @@4
53503 XCHG ECX, EAX
53504 @@4:
53505 JECXZ @@5
53506 PUSH ECX
53507 MOV EDX, [EBX].fDIBHeader
53508 ADD EDX, szBIH
53509 MOV EAX, ESI
53510 CALL TStream.Read
53511 POP ECX
53512 XOR EAX, ECX
53513 JNZ @@eread
53514 @@5:
53515 MOV ECX, [EBX].fDIBSize
53516 @@7:
53517 PUSH ECX
53518 MOV EAX, ESI
53519 CALL TStream.GetPosition
53520 PUSH EAX
53521 MOV EAX, ESI
53522 CALL TStream.GetSize
53523 POP EDX
53524 SUB EAX, EDX
53525 POP ECX // Size = fDIBSize
53526 CMP EAX, ECX // Strm.Size - Strm.Position > Size ?
53527 JL @@8
53528 XCHG ECX, EAX
53529 @@8:
53530 // ++++++++++++++ 26-Oct-2003 VK see comment in Pascal
53531 MOV EAX, [EBX].fDIBSize
53532 CMP ECX, EAX
53533 JGE @@9
53534 SUB EAX, ECX
53535 PUSH EAX
53536 MOV EAX, ESI
53537 PUSH ECX
53538 CALL TStream.GetPosition
53539 POP ECX
53540 POP EDX
53541 CMP EDX, EAX
53542 JG @@9
53544 MOV EAX, ESI
53545 NEG EDX
53546 XOR ECX, ECX
53547 INC ECX
53548 CALL TStream.Seek
53550 MOV ECX, [EBX].fDIBSize
53551 @@9:
53552 // ++++++++++++++
53554 PUSH ECX
53555 MOV EDX, [EBX].fDIBBits
53556 MOV EAX, ESI
53557 CALL TStream.Read
53558 POP ECX
53559 XOR EAX, ECX
53560 POP EAX // Strm.Size - Position
53561 POP ECX // fDIBSize
53562 //JNZ @@eread
53564 // end of reading bitmap
53565 @@eread:
53566 MOV ESP, EBP
53567 POP EBP
53568 POP EDX
53569 JZ @@exit
53570 // not success:
53571 XCHG EAX, ESI
53572 XOR ECX, ECX // ECX = spBegin
53573 CALL TStream.Seek
53574 XCHG EAX, EBX
53575 CALL Clear
53576 @@exit: POP ESI
53577 POP EBX
53578 end;
53579 {$ELSE ASM_VERSION} //Pascal
53580 procedure TBitmap.LoadFromStream(Strm: PStream);
53581 type
53582 TColorsArray = array[ 0..15 ] of TColor;
53583 PColorsArray = ^TColorsArray;
53584 PColor = ^TColor;
53585 var Pos : Integer;
53586 BFH : TBitmapFileHeader;
53588 function ReadBitmap : Boolean;
53589 var Size, Size1: Integer;
53590 BCH: TBitmapCoreHeader;
53591 RGBSize: DWORD;
53592 C: PColor;
53593 Off, HdSz, ColorCount: DWORD;
53594 begin
53595 fHandleType := bmDIB;
53596 Result := False;
53597 if Strm.Read( BFH, Sizeof( BFH ) ) <> Sizeof( BFH ) then Exit;
53598 Off := 0; Size := 0;
53599 if BFH.bfType <> $4D42 then
53600 Strm.Seek( Pos, spBegin )
53601 else
53602 begin
53603 Off := BFH.bfOffBits - Sizeof( BFH );
53604 Size := BFH.bfSize; // don't matter, just <> 0 is good
53605 //Size := Min( BFH.bfSize, Strm.Size - Strm.Position );
53606 end;
53607 RGBSize := 4;
53608 HdSz := Sizeof( TBitmapInfoHeader );
53609 fDIBHeader := AllocMem( 256*sizeof(TRGBQuad) + HdSz );
53610 if Strm.Read( fDIBHeader.bmiHeader.biSize, Sizeof( DWORD ) ) <> Sizeof( DWORD ) then
53611 Exit;
53612 if fDIBHeader.bmiHeader.biSize = HdSz then
53613 begin
53614 if Strm.Read( fDIBHeader.bmiHeader.biWidth, HdSz - Sizeof( DWORD ) ) <>
53615 HdSz - Sizeof( DWORD ) then
53616 Exit;
53618 else
53619 if fDIBHeader.bmiHeader.biSize = Sizeof( TBitmapCoreHeader ) then
53620 begin
53621 RGBSize := 3;
53622 HdSz := Sizeof( TBitmapCoreHeader );
53623 if Strm.Read( BCH.bcWidth, HdSz - Sizeof( DWORD ) ) <>
53624 HdSz - Sizeof( DWORD ) then
53625 Exit;
53626 fDIBHeader.bmiHeader.biSize := Sizeof( TBitmapInfoHeader );
53627 fDIBHeader.bmiHeader.biWidth := BCH.bcWidth;
53628 fDIBHeader.bmiHeader.biHeight := BCH.bcHeight;
53629 fDIBHeader.bmiHeader.biPlanes := BCH.bcPlanes;
53630 fDIBHeader.bmiHeader.biBitCount := BCH.bcBitCount;
53632 else Exit;
53633 fNewPixelFormat := Bits2PixelFormat( fDIBHeader.bmiHeader.biBitCount
53634 * fDIBHeader.bmiHeader.biPlanes );
53635 if (fNewPixelFormat = pf15bit) and (fDIBHeader.bmiHeader.biCompression <> BI_RGB) then
53636 begin
53637 ASSERT( fDIBHeader.bmiHeader.biCompression = BI_BITFIELDS, 'Unsupported bitmap format' );
53638 //fNewPixelFormat := pf16bit;
53639 end;
53640 fWidth := fDIBHeader.bmiHeader.biWidth;
53641 ASSERT( fWidth > 0, 'Bitmap width must be > 0' );
53642 fHeight := Abs(fDIBHeader.bmiHeader.biHeight);
53643 ASSERT( fHeight > 0, 'Bitmap height must be > 0' );
53645 fDIBSize := ScanLineSize * fHeight;
53646 fDIBBits := AllocMem( fDIBSize );
53647 ASSERT( fDIBBits <> nil, 'No memory' );
53649 ColorCount := 0;
53650 if fDIBHeader.bmiHeader.biBitCount <= 8 then
53651 ColorCount := (1 shl fDIBHeader.bmiHeader.biBitCount) * RGBSize
53652 else if fNewPixelFormat in [pf15bit,pf16bit] then
53653 ColorCount := 12;
53655 if Off > 0 then
53656 begin
53657 Off := Off - HdSz;
53658 if (Off <> ColorCount) then
53659 if not(fNewPixelFormat in [pf15bit,pf16bit])
53660 or (Off = 0) //+++ to fix loading 15- and 16-bit bmps with mask omitted
53661 then
53662 ColorCount := Off;
53663 end;
53664 if ColorCount <> 0 then
53665 begin
53666 if Off >= ColorCount then
53667 Off := Off - ColorCount;
53668 if RGBSize = 4 then
53669 begin
53670 if Strm.Read( fDIBheader.bmiColors[ 0 ], ColorCount )
53671 <> DWORD( ColorCount ) then Exit;
53673 else
53674 begin
53675 C := @ fDIBHeader.bmiColors[ 0 ];
53676 while ColorCount > 0 do
53677 begin
53678 if Strm.Read( C^, RGBSize ) <> RGBSize then Exit;
53679 Dec( ColorCount, RGBSize );
53680 Inc( C );
53681 end;
53682 end;
53683 end;
53684 if Off > 0 then
53685 Strm.Seek( Off, spCurrent );
53687 if Size = 0 then
53688 Size := fDIBSize //ScanLineSize * fHeight
53689 else
53690 Size := Min( {Size - Sizeof( TBitmapFileHeader ) - Sizeof( TBitmapInfoHeader )
53691 - ColorCount} fDIBSize, Strm.Size - Strm.Position );
53693 Size1 := Min( Size, fDIBSize );
53695 // +++++++++++++++++++ 26-Oct-2003 by VK
53696 if (Size1 < fDIBSize)
53697 and (DWORD( fDIBSize - Size1 ) <= Strm.Position) then
53698 begin
53699 Strm.Seek( Size1 - fDIBSize, spCurrent );
53700 Size1 := fDIBSize;
53701 end;
53702 // +++++++++++++++++++ to fix some "incorrect" bitmaps while loading
53704 if Strm.Read( fDIBBits^, Size1 ) <> DWORD( Size1 ) then Exit;
53705 if Size > Size1 then
53706 Strm.Seek( Size - Size1, spCurrent );
53708 Result := True;
53709 end;
53710 {var ColorsArray: PColorsArray;
53711 DC: HDC;
53712 Old: HBitmap;}
53713 begin
53714 Clear;
53715 Pos := Strm.Position;
53716 if not ReadBitmap then
53717 begin
53718 Strm.Seek( Pos, spBegin );
53719 Clear;
53720 end;
53721 {else
53722 begin
53723 if (fDIBBits <> nil) and (fDIBHeader.bmiHeader.biBitCount >= 4) then
53724 begin
53725 ColorsArray := @ fDIBHeader.bmiColors[ 0 ];
53726 if ColorsArray[ 7 ] = $C0C0C0 then
53727 if ColorsArray[ 8 ] = $808080 then
53728 if GetHandle <> 0 then
53729 begin
53730 DC := CreateCompatibleDC( 0 );
53731 Old := SelectObject( DC, fHandle );
53732 SetDIBColorTable( DC, 0, 16, fDIBHeader.bmiColors[ 0 ] );
53733 SelectObject( DC, Old );
53734 DeleteDC( DC );
53735 end;
53736 end;
53737 end;}
53738 end;
53739 {$ENDIF ASM_VERSION}
53741 ////////////////// bitmap RLE-decoding and loading - by Vyacheslav A. Gavrik
53743 //[procedure DecodeRLE4]
53744 procedure DecodeRLE4(Bmp:PBitmap;Data:Pointer); // by Vyacheslav A. Gavrik
53745 procedure OddMove(Src,Dst:PByte;Size:Integer);
53746 begin
53747 if Size=0 then Exit;
53748 repeat
53749 Dst^:=(Dst^ and $F0)or(Src^ shr 4);
53750 Inc(Dst);
53751 Dst^:=(Dst^ and $0F)or(Src^ shl 4);
53752 Inc(Src);
53753 Dec(Size);
53754 until Size=0;
53755 end;
53756 procedure OddFill(Mem:PByte;Size,Value:Integer);
53757 begin
53758 Value:=(Value shr 4)or(Value shl 4);
53759 Mem^:=(Mem^ and $F0)or(Value and $0F);
53760 Inc(Mem);
53761 if Size>1 then FillChar(Mem^,Size,Value);
53762 Mem^:=(Mem^ and $0F)or(Value and $F0);
53763 end;
53765 pb: PByte;
53766 x,y,z,i: Integer;
53767 begin
53768 pb:=Data; x:=0; y:=0;
53769 if Bmp.fScanLineSize = 0 then
53770 Bmp.ScanLineSize;
53771 while y<Bmp.Height do
53772 begin
53773 if pb^=0 then
53774 begin
53775 Inc(pb);
53776 z:=pb^;
53777 case pb^ of
53778 0: begin
53779 Inc(y);
53780 x:=0;
53781 end;
53782 1: Break;
53783 2: begin
53784 Inc(pb); Inc(x,pb^);
53785 Inc(pb); Inc(y,pb^);
53786 end;
53787 else
53788 begin
53789 Inc(pb);
53790 i:=(z+1)shr 1;
53791 if(z and 2)=2 then Inc(i);
53792 if((x and 1)=1)and(x+i<Bmp.Width)then
53793 OddMove(pb,@PByteArray(Integer( Bmp.fDIBBits ) + Bmp.fScanLineSize * y)[x shr 1],i)
53794 else
53795 Move(pb^,PByteArray(Integer( Bmp.fDIBBits ) + Bmp.fScanLineSize * y)[x shr 1],i);
53796 Inc(pb,i-1);
53797 Inc(x,z);
53798 end;
53799 end;
53800 end else
53801 begin
53802 z:=pb^;
53803 Inc(pb);
53804 if((x and 1)=1)and(x+z<Bmp.Width)then
53805 OddFill(@PByteArray(Integer( Bmp.fDIBBits ) + Bmp.fScanLineSize * y)[x shr 1],z shr 1,pb^)
53806 else
53807 FillChar(PByteArray(Integer( Bmp.fDIBBits ) + Bmp.fScanLineSize * y)[x shr 1],z shr 1,pb^);
53808 Inc(x,z);
53809 end;
53810 Inc(pb);
53811 end;
53812 end;
53814 //[procedure DecodeRLE8]
53815 procedure DecodeRLE8(Bmp:PBitmap;Data:Pointer); // by Vyacheslav A. Gavrik
53817 pb: PByte;
53818 x,y,z,i: Integer;
53819 begin
53820 pb:=Data; y:=0; x:=0;
53821 if Bmp.fScanLineSize = 0 then
53822 Bmp.ScanLineSize;
53824 while y<Bmp.Height do
53825 begin
53826 if pb^=0 then
53827 begin
53828 Inc(pb);
53829 case pb^ of
53830 0: begin
53831 Inc(y);
53832 x:=0;
53833 end;
53834 1: Break;
53835 2: begin
53836 Inc(pb); Inc(x,pb^);
53837 Inc(pb); Inc(y,pb^);
53838 end;
53839 else
53840 begin
53841 i:=pb^;
53842 z:=(i+1)and(not 1);
53843 Inc(pb);
53844 Move(pb^,PByteArray(Integer( Bmp.fDIBBits ) + Bmp.fScanLineSize * y)[x],z);
53845 Inc(pb,z-1);
53846 Inc(x,i);
53847 end;
53848 end;
53849 end else
53850 begin
53851 i:=pb^; Inc(pb);
53852 FillChar(PByteArray(Integer( Bmp.fDIBBits ) + Bmp.fScanLineSize * y)[x],i,pb^);
53853 Inc(x,i);
53854 end;
53855 Inc(pb);
53856 end;
53857 end;
53859 //[function TBitmap.LoadFromFileEx]
53860 function TBitmap.LoadFromFileEx(const Filename: String): Boolean; // by Vyacheslav A. Gavrik
53861 var Strm: PStream;
53862 begin
53863 Strm := NewReadFileStream( Filename );
53864 Result := LoadFromStreamEx(Strm);
53865 Strm.Free;
53866 end;
53868 //[function TBitmap.LoadFromStreamEx]
53869 function TBitmap.LoadFromStreamEx(Strm: PStream): Boolean; // by Vyacheslav A. Gavrik
53870 var Pos : Integer;
53872 function ReadBitmap : Boolean;
53873 var Off, Size, ColorCount: Integer;
53874 BFH : TBitmapFileHeader;
53875 BFHValid: Boolean;
53876 Buffer: Pointer;
53877 begin
53878 fHandleType := bmDIB;
53879 Result := False;
53880 BFHValid := FALSE;
53881 if Strm.Read( BFH, Sizeof( BFH ) ) <> Sizeof( BFH ) then Exit;
53882 Off := 0; Size := 0;
53883 if BFH.bfType <> $4D42 then
53884 Strm.Seek( Pos, spBegin )
53885 else
53886 begin
53887 BFHValid := TRUE;
53888 Off := BFH.bfOffBits;
53889 Size := Strm.GetSize;
53890 end;
53891 GetMem( fDIBHeader, 256*sizeof(TRGBQuad) + sizeof(TBitmapInfoHeader) );
53892 if Strm.Read( fDIBHeader^, Sizeof(TBitmapInfoHeader) ) <> Sizeof(TBitmapInfoHeader) then
53893 Exit;
53894 //if fDIBHeader.bmiHeader.biCompression = BI_RGB then
53895 {if fDIBHeader.bmiHeader.biCompression = BI_BITFIELDS then
53896 //BI_RGB here????
53897 Strm.Read( fDIBHeader.bmiColors[ 0 ], 3 * Sizeof( DWORD ) );}
53899 fNewPixelFormat := Bits2PixelFormat( fDIBHeader.bmiHeader.biBitCount
53900 * fDIBHeader.bmiHeader.biPlanes );
53902 fWidth := fDIBHeader.bmiHeader.biWidth;
53903 ASSERT( fWidth > 0, 'Bitmap width must be > 0' );
53904 fHeight := Abs(fDIBHeader.bmiHeader.biHeight);
53905 ASSERT( fHeight > 0, 'Bitmap height must be > 0' );
53907 fDIBSize := ScanLineSize * fHeight;
53908 GetMem( fDIBBits, fDIBSize );
53909 ASSERT( fDIBBits <> nil, 'No memory' );
53910 ASSERT( (fDIBHeader.bmiHeader.biCompression and
53911 (BI_RLE8 or BI_RLE4 or BI_RLE8 or BI_BITFIELDS) <> 0) or
53912 (fDIBHeader.bmiHeader.biCompression = BI_RGB),
53913 'Unknown compression algorithm');
53915 ColorCount := 0;
53916 if fDIBHeader.bmiHeader.biBitCount <= 8 then
53917 ColorCount := (1 shl fDIBHeader.bmiHeader.biBitCount) * Sizeof( TRGBQuad )
53918 else if fNewPixelFormat in [ pf16bit ] then
53919 ColorCount := 12;
53921 if Off > 0 then
53922 begin
53923 Off := Off - SizeOf( TBitmapFileHeader ) - Sizeof( TBitmapInfoHeader );
53924 if Off <> ColorCount then
53925 ColorCount := Off;
53926 end;
53927 if fDIBHeader.bmiHeader.biCompression = BI_BITFIELDS then
53928 begin
53929 PDWORD( DWORD( @ fDIBHeader.bmiColors[ 0 ] ) + 8 )^ := ( $00001F );
53930 PDWORD( DWORD( @ fDIBHeader.bmiColors[ 0 ] ) + 4 )^ := ( $0007E0 );
53931 TColor( fDIBHeader.bmiColors[ 0 ] ) := ( $00F800 );
53932 end;
53934 if ColorCount <> 0 then
53935 if Strm.Read( fDIBheader.bmiColors[ 0 ], ColorCount )
53936 <> DWORD( ColorCount ) then Exit;
53938 if not BFHValid then
53939 Size := fDIBSize
53940 else
53941 if(fDIBHeader.bmiHeader.biCompression = BI_RLE8)
53942 or (fDIBHeader.bmiHeader.biCompression=BI_RLE4) then
53943 Size := BFH.bfSize - BFH.bfOffBits
53944 else
53945 begin
53946 if Integer( Strm.Size - BFH.bfOffBits) - Pos > Integer(Size) then
53947 Size := fDIBSize
53948 else
53949 Size := Strm.Size - BFH.bfOffBits - DWORD( Pos );
53950 end;
53952 if (fDIBHeader.bmiHeader.biCompression = BI_RGB) or
53953 (fDIBHeader.bmiHeader.biCompression = BI_BITFIELDS) then
53954 begin
53955 if Strm.Read( fDIBBits^, Size ) <> DWORD( Size ) then
53956 //Exit;
53958 else
53959 begin
53960 GetMem(Buffer,Size);
53961 if Strm.Read(Buffer^,Size) <> DWORD( Size ) then Exit;
53963 if fDIBHeader.bmiHeader.biCompression=BI_RLE8 then
53964 DecodeRLE8(@Self,Buffer)
53965 else
53966 DecodeRLE4(@Self,Buffer);
53968 fDIBHeader.bmiHeader.biCompression := BI_RGB;
53969 FreeMem(Buffer);
53970 end;
53972 Result := True;
53973 end;
53974 begin
53975 Clear;
53976 Pos := Strm.Position;
53977 result := ReadBitmap;
53978 if not result then
53979 begin
53980 Strm.Seek( Pos, spBegin );
53981 Clear;
53982 end;
53983 end;
53985 ///////////////////////////
53987 {$IFDEF ASM_VERSION}
53988 //[function TBitmap.ReleaseHandle]
53989 function TBitmap.ReleaseHandle: HBitmap;
53991 PUSH EBX
53992 MOV EBX, EAX
53993 XOR EDX, EDX
53994 CALL SetHandleType
53995 MOV EAX, EBX
53996 CALL GetHandle
53997 TEST EAX, EAX
53998 JZ @@exit
54000 CMP [EBX].fDIBAutoFree, 0
54001 JZ @@1
54002 MOV EAX, [EBX].fDIBSize
54003 PUSH EAX
54004 CALL System.@GetMem
54005 MOV EDX, EAX
54006 XCHG EAX, [EBX].fDIBBits
54007 POP ECX
54008 CALL System.Move
54009 @@1:
54010 XOR EAX, EAX
54011 MOV [EBX].fDIBAutoFree, AL
54012 XCHG EAX, [EBX].fHandle
54014 @@exit: POP EBX
54015 end;
54016 {$ELSE ASM_VERSION} //Pascal
54017 function TBitmap.ReleaseHandle: HBitmap;
54018 var OldBits: Pointer;
54019 begin
54020 HandleType := bmDIB;
54021 Result := GetHandle;
54022 if Result = 0 then Exit; // only when bitmap is empty
54023 if fDIBAutoFree then
54024 begin
54025 OldBits := fDIBBits;
54026 GetMem( fDIBBits, fDIBSize );
54027 Move( OldBits^, fDIBBits^, fDIBSize );
54028 fDIBAutoFree := FALSE;
54029 end;
54030 fHandle := 0;
54031 end;
54032 {$ENDIF ASM_VERSION}
54034 {$IFDEF ASM_VERSION}
54035 //[procedure TBitmap.SaveToFile]
54036 procedure TBitmap.SaveToFile(const Filename: String);
54038 PUSH EAX
54039 PUSH EDX
54040 CALL GetEmpty
54041 POP EAX
54042 JZ @@exit
54043 CALL NewWriteFileStream
54044 XCHG EDX, EAX
54045 POP EAX
54046 PUSH EDX
54047 CALL SaveToStream
54048 POP EAX
54049 CALL TObj.Free
54050 PUSH EAX
54051 @@exit: POP EAX
54052 end;
54053 {$ELSE ASM_VERSION} //Pascal
54054 procedure TBitmap.SaveToFile(const Filename: String);
54055 var Strm: PStream;
54056 begin
54057 if Empty then Exit;
54058 Strm := NewWritefileStream( Filename );
54059 SaveToStream( Strm );
54060 Strm.Free;
54061 end;
54062 {$ENDIF ASM_VERSION}
54064 {$IFDEF ASM_VERSION}
54065 //[procedure TBitmap.SaveToStream]
54066 procedure TBitmap.SaveToStream(Strm: PStream);
54067 type tBFH = TBitmapFileHeader;
54068 tBIH = TBitmapInfoHeader;
54069 const szBIH = Sizeof( tBIH );
54070 szBFH = Sizeof( tBFH );
54072 PUSH EBX
54073 PUSH ESI
54074 MOV EBX, EAX
54075 MOV ESI, EDX
54076 CALL GetEmpty
54077 JZ @@exit
54078 MOV EAX, ESI
54079 CALL TStream.GetPosition
54080 PUSH EAX
54082 MOV EAX, EBX
54083 XOR EDX, EDX // EDX = bmDIB
54084 CALL SetHandleType
54085 XOR EAX, EAX
54086 MOV EDX, [EBX].fDIBHeader
54087 MOVZX ECX, [EDX].TBitmapInfoHeader.biBitCount
54088 CMP CL, 8
54089 JG @@1
54090 MOV AL, 4
54091 SHL EAX, CL
54092 @@1:
54093 PUSH EAX // ColorsSize
54094 LEA ECX, [EAX + szBFH + szBIH]
54095 CMP [EDX].TBitmapInfoHeader.biCompression, 0
54096 JZ @@10
54097 ADD ECX, 74
54098 @@10:
54099 PUSH ECX // BFH.bfOffBits
54100 PUSH 0
54101 ADD ECX, [EBX].fDIBSize
54102 PUSH ECX
54103 MOV CX, $4D42
54104 PUSH CX
54105 XOR ECX, ECX
54106 MOV EDX, ESP
54107 MOV CL, szBFH
54108 PUSH ECX
54109 MOV EAX, ESI
54110 CALL TStream.Write
54111 POP ECX
54112 ADD ESP, szBFH
54113 XOR EAX, ECX
54114 POP ECX // ColorsSize
54115 JNZ @@ewrite
54117 MOV EDX, [EBX].fDIBHeader
54118 CMP [EDX].TBitmapInfoHeader.biCompression, 0
54119 JZ @@11
54120 ADD ECX, 74
54121 @@11:
54123 ADD ECX, szBIH
54124 PUSH ECX
54125 MOV EAX, ESI
54126 CALL TStream.Write
54127 POP ECX
54128 XOR EAX, ECX
54129 JNZ @@ewrite
54131 MOV ECX, [EBX].fDIBSize
54132 MOV EDX, [EBX].fDIBBits
54133 MOV EAX, ESI
54134 PUSH ECX
54135 CALL TStream.Write
54136 POP ECX
54137 XOR EAX, ECX
54139 @@ewrite:
54140 POP EDX
54141 JZ @@exit
54142 XCHG EAX, ESI
54143 XOR ECX, ECX
54144 CALL TStream.Seek
54145 @@exit:
54146 POP ESI
54147 POP EBX
54148 end;
54149 {$ELSE ASM_VERSION} //Pascal
54150 procedure TBitmap.SaveToStream(Strm: PStream);
54151 var BFH : TBitmapFileHeader;
54152 Pos : Integer;
54153 function WriteBitmap : Boolean;
54154 var ColorsSize, BitsSize, Size : Integer;
54155 begin
54156 Result := False;
54157 if Empty then Exit;
54158 HandleType := bmDIB; // convert to DIB if DDB
54159 FillChar( BFH, Sizeof( BFH ), 0 );
54160 ColorsSize := 0;
54161 with fDIBHeader.bmiHeader do
54162 if biBitCount <= 8 then
54163 ColorsSize := (1 shl biBitCount) * Sizeof( TRGBQuad )
54164 {else
54165 if biCompression <> 0 then
54166 ColorsSize := 12};
54167 BFH.bfOffBits := Sizeof( BFH ) + Sizeof( TBitmapInfoHeader ) + ColorsSize;
54168 BitsSize := fDIBSize; //ScanLineSize * fHeight;
54169 BFH.bfSize := BFH.bfOffBits + DWord( BitsSize );
54170 BFH.bfType := $4D42; // 'BM';
54171 if fDIBHeader.bmiHeader.biCompression <> 0 then
54172 begin
54173 ColorsSize := 12 + 16*sizeof(TRGBQuad);
54174 Inc( BFH.bfOffBits, ColorsSize );
54175 end;
54176 if Strm.Write( BFH, Sizeof( BFH ) ) <> Sizeof( BFH ) then Exit;
54177 Size := Sizeof( TBitmapInfoHeader ) + ColorsSize;
54178 if Strm.Write( fDIBHeader^, Size ) <> DWORD(Size) then Exit;
54179 if Strm.Write( fDIBBits^, BitsSize ) <> DWord( BitsSize ) then Exit;
54180 Result := True;
54181 end;
54182 begin
54183 Pos := Strm.Position;
54184 if not WriteBitmap then
54185 Strm.Seek( Pos, spBegin );
54186 end;
54187 {$ENDIF ASM_VERSION}
54189 {$IFDEF ASM_VERSION}
54190 //[procedure TBitmap.SetHandle]
54191 procedure TBitmap.SetHandle(const Value: HBitmap);
54192 const szB = sizeof( tagBitmap );
54194 PUSH EAX
54195 PUSH EDX
54196 CALL Clear
54197 POP ECX
54198 JECXZ @@exit
54199 PUSH ECX
54200 ADD ESP, -szB
54201 PUSH ESP
54202 PUSH szB
54203 PUSH ECX
54204 CALL GetObject
54205 POP EDX
54206 POP EDX
54207 POP ECX
54208 ADD ESP, 12
54209 TEST EAX, EAX
54210 POP EAX
54211 JZ @@exit
54212 XCHG EAX, [ESP]
54213 MOV [EAX].fWidth, EDX
54214 MOV [EAX].fHeight, ECX
54215 POP EDX
54216 MOV [EAX].fHandle, EDX
54217 MOV [EAX].fHandleType, 1
54218 PUSH EAX
54219 @@exit: POP EAX
54220 end;
54221 {$ELSE ASM_VERSION} //Pascal
54222 procedure TBitmap.SetHandle(const Value: HBitmap);
54223 var B: tagBitmap;
54224 begin
54225 Clear;
54226 if Value = 0 then Exit;
54227 if GetObject( Value, Sizeof( B ), @B ) = 0 then Exit;
54228 fHandle := Value;
54229 fWidth := B.bmWidth;
54230 fHeight := B.bmHeight;
54231 fHandleType := bmDDB;
54232 end;
54233 {$ENDIF ASM_VERSION}
54235 //[procedure TBitmap.SetWidth]
54236 procedure TBitmap.SetWidth(const Value: Integer);
54237 begin
54238 if fWidth = Value then Exit;
54239 fWidth := Value;
54240 FormatChanged;
54241 end;
54243 {$IFDEF ASM_VERSION}
54244 //[procedure TBitmap.SetHeight]
54245 procedure TBitmap.SetHeight(const Value: Integer);
54247 CMP EDX, [EAX].fHeight
54248 JE @@exit
54249 PUSHAD
54250 XOR EDX, EDX
54251 INC EDX
54252 CALL SetHandleType
54253 POPAD
54254 MOV [EAX].fHeight, EDX
54255 CALL FormatChanged
54256 @@exit:
54257 end;
54258 {$ELSE ASM_VERSION} //Pascal
54259 procedure TBitmap.SetHeight(const Value: Integer);
54260 begin
54261 if fHeight = Value then Exit;
54263 HandleType := bmDDB;
54264 // Not too good, but provides correct changing of height
54265 // preserving previous image
54267 fHeight := Value;
54268 FormatChanged;
54269 end;
54270 {$ENDIF ASM_VERSION}
54272 {$IFDEF ASM_VERSION}
54273 //[procedure TBitmap.SetPixelFormat]
54274 procedure TBitmap.SetPixelFormat(Value: TPixelFormat);
54276 PUSH EBX
54277 MOV EBX, EAX
54278 //////////////////////
54279 CALL GetEmpty // if Empty then Exit;
54280 JZ @@exit //
54281 MOV EAX, EBX //
54282 //////////////////////
54283 PUSH EDX
54284 CALL GetPixelFormat
54285 POP EDX
54286 CMP EAX, EDX
54287 JE @@exit
54288 TEST EDX, EDX
54289 MOV EAX, EBX
54290 JNE @@2
54291 // Value = pfDevice (=0)
54292 POP EBX
54293 INC EDX // EDX = bmDDB
54294 JMP SetHandleType
54295 @@2:
54296 MOV [EBX].fNewPixelFormat, DL
54297 CMP DL, pf16bit
54298 JNZ @@3
54299 DEC EDX
54300 @@3: PUSH EDX
54301 XOR EDX, EDX
54302 CALL SetHandleType
54303 MOV EAX, [EBX].fDIBHeader
54304 MOVZX EAX, [EAX].TBitmapInfoHeader.biBitCount
54305 CALL Bits2PixelFormat
54306 POP EDX
54307 CMP AL, DL
54308 XCHG EAX, EBX
54309 @@exit:
54310 POP EBX
54311 JNE FormatChanged
54312 end;
54313 {$ELSE ASM_VERSION} //Pascal
54314 procedure TBitmap.SetPixelFormat(Value: TPixelFormat);
54315 begin
54316 if PixelFormat = Value then Exit;
54317 if Empty then Exit;
54318 if Value = pfDevice then
54319 HandleType := bmDDB
54320 else
54321 begin
54322 fNewPixelFormat := Value;
54323 //if Value = pf16bit then Value := pf15bit;
54324 HandleType := bmDIB;
54325 if Value <> Bits2PixelFormat( fDIBHeader.bmiHeader.biBitCount ) then
54326 FormatChanged;
54327 end;
54328 end;
54329 {$ENDIF ASM_VERSION}
54331 //[FUNCTION CalcScanLineSize]
54332 {$IFDEF ASM_VERSION}
54333 function CalcScanLineSize( Header: PBitmapInfoHeader ): Integer;
54335 MOVZX EDX, [EAX].TBitmapInfoHeader.biBitCount
54336 MOV EAX, [EAX].TBitmapInfoHeader.biWidth
54337 MUL EDX
54338 ADD EAX, 31
54339 SHR EAX, 3
54340 AND EAX, -4
54341 end;
54342 {$ELSE ASM_VERSION} //Pascal
54343 function CalcScanLineSize( Header: PBitmapInfoHeader ): Integer;
54344 begin
54345 //Result := ((Header.biBitCount * Header.biWidth + 31)
54346 // shr 5) * 4;
54347 Result := ((Header.biBitCount * Header.biWidth + 31) shr 3) and $FFFFFFFC;
54348 end;
54349 {$ENDIF ASM_VERSION}
54350 //[END CalcScanLineSize]
54352 //[PROCEDURE FillBmpWithBkColor]
54353 {$IFDEF ASM_VERSION}
54354 procedure FillBmpWithBkColor( Bmp: PBitmap; DC2: HDC; oldWidth, oldHeight: Integer );
54356 PUSH EBX
54357 PUSH ESI
54358 XCHG EAX, EBX
54359 PUSH EDX // [EBP-12] = DC2
54360 PUSH ECX // [EBP-16] = oldWidth
54361 MOV EAX, [EBX].TBitmap.fBkColor
54362 CALL Color2RGB
54363 TEST EAX, EAX
54364 JZ @@exit
54365 XCHG ESI, EAX // ESI = Color2RGB( Bmp.fBkColor )
54366 MOV EAX, EBX
54367 CALL TBitmap.GetHandle
54368 TEST EAX, EAX
54369 JZ @@exit
54370 PUSH EAX //fHandle
54371 PUSH dword ptr [EBP-12] //DC2
54372 CALL SelectObject
54373 PUSH EAX // [EBP-20] = oldBmp
54374 PUSH ESI
54375 CALL CreateSolidBrush
54376 XCHG ESI, EAX // ESI = Br
54377 PUSH [EBX].TBitmap.fHeight
54378 PUSH [EBX].TBitmap.fWidth
54379 MOV EAX, [oldHeight]
54380 MOV EDX, [EBP-16] //oldWidth
54381 CMP EAX, [EBX].TBitmap.fHeight
54382 JL @@fill
54383 CMP EDX, [EBX].TBitmap.fWidth
54384 JGE @@nofill
54385 @@fill: CMP EAX, [EBX].TBitmap.fHeight
54386 JNE @@1
54387 XOR EAX, EAX
54388 @@1:
54389 CMP EDX, [EBX].TBitmap.fWidth
54390 JNZ @@2
54392 @@2: PUSH EAX
54393 PUSH EDX
54395 MOV EDX, ESP
54396 PUSH ESI
54397 PUSH EDX
54398 PUSH dword ptr [EBP-12] //DC2
54399 CALL Windows.FillRect
54400 POP ECX
54401 POP ECX
54402 @@nofill:
54403 POP ECX
54404 POP ECX
54405 PUSH ESI //Br
54406 CALL DeleteObject
54407 PUSH dword ptr [EBP-12] //DC2
54408 CALL SelectObject
54409 @@exit:
54410 POP ECX
54411 POP EDX
54412 POP ESI
54413 POP EBX
54414 end;
54415 {$ELSE ASM_VERSION} //Pascal
54416 procedure FillBmpWithBkColor( Bmp: PBitmap; DC2: HDC; oldWidth, oldHeight: Integer );
54417 var oldBmp: HBitmap;
54418 R: TRect;
54419 Br: HBrush;
54420 begin
54421 with Bmp{-}^{+} do
54422 if Color2RGB( fBkColor ) <> 0 then
54423 if (oldWidth < fWidth) or (oldHeight < fHeight) then
54424 if GetHandle <> 0 then
54425 begin
54426 oldBmp := SelectObject( DC2, fHandle );
54427 ASSERT( oldBmp <> 0, 'Can not select bitmap to DC' );
54428 Br := CreateSolidBrush( Color2RGB( fBkColor ) );
54429 R := MakeRect( oldWidth, oldHeight, fWidth, fHeight );
54430 if oldWidth = fWidth then
54431 R.Left := 0;
54432 if oldHeight = fHeight then
54433 R.Top := 0;
54434 Windows.FillRect( DC2, R, Br );
54435 DeleteObject( Br );
54436 SelectObject( DC2, oldBmp );
54437 end;
54438 end;
54439 {$ENDIF ASM_VERSION}
54440 //[END FillBmpWithBkColor]
54442 const BitCounts: array[ TPixelFormat ] of Byte = ( 0, 1, 4, 8, 16, 16, 24, 32, 0 );
54443 {$IFDEF ASM_VERSION}
54444 //[procedure TBitmap.FormatChanged]
54445 procedure TBitmap.FormatChanged;
54446 type tBIH = TBitmapInfoHeader;
54447 tBmp = tagBitmap;
54448 const szBIH = Sizeof( tBIH );
54449 szBmp = Sizeof( tBmp );
54451 PUSH EAX
54452 CALL GetEmpty
54453 POP EAX
54454 JZ @@exit
54455 PUSHAD
54456 MOV EBX, EAX
54457 CALL [EBX].fDetachCanvas
54458 XOR EAX, EAX
54459 MOV [EBX].fScanLineSize, EAX
54460 MOV [EBX].fGetDIBPixels, EAX
54461 MOV [EBX].fSetDIBPixels, EAX
54462 MOV ESI, [EBX].fWidth // ESI := oldWidth
54463 MOV EDI, [EBX].fHeight // EDI := oldHeight
54464 MOV ECX, [EBX].fDIBBits
54465 JECXZ @@noDIBBits
54466 MOV EAX, [EBX].fDIBHeader
54467 MOV ESI, [EAX].TBitmapInfo.bmiHeader.biWidth
54468 MOV EDI, [EAX].TBitmapInfo.bmiHeader.biHeight
54469 TEST EDI, EDI
54470 JGE @@1
54471 NEG EDI
54472 @@1: JMP @@createDC2
54473 @@noDIBBits:
54474 MOV ECX, [EBX].fHandle
54475 JECXZ @@createDC2
54476 ADD ESP, -24 // -szBmp
54477 PUSH ESP
54478 PUSH 24 //szBmp
54479 PUSH ECX
54480 CALL GetObject
54481 XCHG ECX, EAX
54482 JECXZ @@2
54483 MOV ESI, [ESP].tBmp.bmWidth
54484 MOV EDI, [ESP].tBmp.bmHeight
54485 @@2: ADD ESP, 24 //szBmp
54486 @@createDC2:
54487 PUSH 0
54488 CALL CreateCompatibleDC
54489 PUSH EAX // > DC2
54490 CMP [EBX].fHandleType, bmDDB
54491 JNE @@DIB_handle_type
54492 PUSH 0
54493 CALL GetDC
54494 PUSH EAX // > DC0
54495 PUSH [EBX].fHeight
54496 PUSH [EBX].fWidth
54497 PUSH EAX
54498 CALL CreateCompatibleBitmap
54499 XCHG EBP, EAX // EBP := NewHandle
54500 PUSH 0
54501 CALL ReleaseDC // <
54502 POP EDX
54503 PUSH EDX // EDX := DC2
54504 PUSH EBP
54505 PUSH EDX
54506 CALL SelectObject
54507 PUSH EAX // > OldBmp
54508 PUSH [EBX].fHeight // prepare Rect(0,0,fWidth,fHeight)
54509 PUSH [EBX].fWidth
54510 PUSH 0
54511 PUSH 0
54512 MOV EAX, [EBX].fBkColor
54513 CALL Color2RGB
54514 PUSH EAX
54515 CALL CreateSolidBrush
54516 MOV EDX, ESP
54517 PUSH EAX // > Br
54518 PUSH EAX
54519 PUSH EDX
54520 PUSH dword ptr [ESP+32] // (DC2)
54521 CALL Windows.FillRect
54522 CALL DeleteObject // <
54523 ADD ESP, 16 // remove Rect
54524 MOV ECX, [EBX].fDIBBits
54525 JECXZ @@draw
54526 PUSH dword ptr [ESP+4] // (DC2)
54527 CALL SelectObject // < (OldBmp)
54528 PUSH DIB_RGB_COLORS // : DIB_RGB_COLORS
54529 PUSH [EBX].fDIBHeader // : fDIBHeader
54530 PUSH [EBX].fDIBBits // : fDIBBits
54531 PUSH [EBX].fHeight // : fHeight
54532 PUSH 0 // : 0
54533 PUSH EBP // : NewHandle
54534 PUSH dword ptr [ESP+24] // (DC2)
54535 CALL SetDIBits
54536 JMP @@clearData
54537 @@draw:
54538 MOV EDX, [ESP+4]
54539 PUSH EDX // prepare DC2 for SelectObject
54540 MOV EAX, EBX
54541 XOR ECX, ECX
54542 PUSH ECX
54543 CALL Draw
54544 CALL SelectObject
54545 @@clearData:
54546 MOV EAX, EBX
54547 CALL ClearData
54548 MOV [EBX].fHandle, EBP
54550 JMP @@fillBkColor
54552 @@DIB_handle_type: // [ESP] = DC2
54553 MOVZX EAX, [EBX].fNewPixelFormat
54554 @@getBitsPixel:
54555 XCHG ECX, EAX
54556 MOV CL, [ECX] + offset BitCounts
54557 MOVZX EAX, [DefaultPixelFormat]
54558 JECXZ @@getBitsPixel
54559 XOR EBP, EBP // NewHandle := 0
54560 MOV EAX, [EBX].fWidth // EAX := fWidth
54561 MOV EDX, [EBX].fHeight // EDX := fHeight
54562 CALL PrepareBitmapHeader
54563 PUSH EAX // > NewHeader
54564 CMP [EBX].fNewPixelFormat, pf16bit
54565 JNE @@newHeaderReady
54566 CALL PreparePF16bit
54567 @@newHeaderReady:
54568 POP EAX
54569 PUSH EAX
54570 CALL CalcScanLineSize
54571 MOV EDX, [EBX].fHeight
54572 MUL EDX
54573 PUSH EAX // > sizeBits
54575 {$IFDEF _FP}
54576 CALL GetMem
54577 {$ELSE}
54578 CALL System.@GetMem
54579 {$ENDIF}
54580 PUSH EAX // > NewBits
54581 PUSH DIB_RGB_COLORS
54582 PUSH dword ptr [ESP+12] // (NewHeader)
54583 PUSH EAX
54584 MOV EAX, [EBX].fHeight
54585 CMP EAX, EDI
54586 {$IFDEF USE_CMOV}
54587 CMOVG EAX, EDI
54588 {$ELSE}
54589 JLE @@3
54590 MOV EAX, EDI
54591 @@3: {$ENDIF}
54593 PUSH EAX
54594 PUSH 0
54595 MOV EAX, EBX
54596 CALL GetHandle
54597 PUSH EAX
54598 PUSH dword ptr [ESP+36] // (DC2)
54599 CALL GetDIBits
54601 MOV EDX, [EBX].fHeight
54602 CMP EDX, EDI
54603 {$IFDEF USE_CMOV}
54604 CMOVG EDX, EDI
54605 {$ELSE}
54606 JLE @@30
54607 MOV EDX, EDI
54608 @@30: {$ENDIF}
54610 CMP EAX, EDX
54611 JE @@2clearData
54613 POP EAX
54614 {$IFDEF _FP}
54615 CALL FreeMem
54616 {$ELSE}
54617 CALL System.@FreeMem
54618 {$ENDIF}
54620 XOR EAX, EAX
54621 PUSH EAX
54623 MOV EDX, ESP // EDX = @NewBits
54624 MOV ECX, [ESP+8] // ECX = @NewHeader
54625 PUSH EAX // -> 0
54626 PUSH EAX // -> 0
54627 PUSH EDX // -> @NewBits
54628 PUSH DIB_RGB_COLORS // -> DIB_RGB_COLORS
54629 PUSH ECX // -> @NewHeader
54630 PUSH dword ptr [ESP+32] // -> DC2
54631 CALL CreateDIBSection
54633 XOR ESI, -1 // use OldWidth to store NewDIBAutoFree flag
54635 XCHG EBP, EAX // EBP := NewHandle
54636 PUSH EBP
54637 PUSH dword ptr [ESP+16] // -> DC2
54638 CALL SelectObject
54639 PUSH EAX // save oldBmp
54640 MOV EDX, [ESP+16] // DC2 -> EDX (DC)
54641 XOR ECX, ECX // 0 -> ECX (X)
54642 PUSH ECX // 0 -> stack (Y)
54643 MOV EAX, EBX
54644 CALL TBitmap.Draw
54645 PUSH dword ptr [ESP+16] // -> DC2
54646 CALL SelectObject
54648 @@2clearData:
54649 MOV EAX, EBX
54650 CALL ClearData
54652 POP [EBX].fDIBBits
54653 POP [EBX].fDIBSize
54654 POP [EBX].fDIBHeader
54655 MOV [EBX].fHandle, EBP
54657 TEST ESI, ESI
54658 MOV [EBX].fDIBAutoFree, 0
54659 JGE @@noDIBautoFree
54660 INC [EBX].fDIBAutoFree
54661 @@noDIBautoFree:
54663 @@fillBkColor:
54664 MOV ECX, [EBX].fFillWithBkColor
54665 JECXZ @@deleteDC2
54666 POP EDX // (DC2)
54667 PUSH EDX
54668 PUSH EDI
54669 XCHG ECX, ESI
54670 XCHG EAX, EBX
54671 CALL ESI
54672 @@deleteDC2:
54673 CALL DeleteDC
54674 POPAD
54675 @@exit:
54676 end;
54677 {$ELSE ASM_VERSION} //Pascal
54678 procedure TBitmap.FormatChanged;
54679 // This method is used whenever Width, Height, PixelFormat or HandleType
54680 // properties are changed.
54681 // Old image will be drawn here to a new one (excluding cases when
54682 // old width or height was 0, and / or new width or height is 0).
54683 // To avoid inserting this code into executable, try not to change
54684 // properties Width / Height of bitmat after it is created using
54685 // NewBitmap( W, H ) function or after it is loaded from file, stream
54686 // or resource.
54688 var B: tagBitmap;
54689 oldBmp, NewHandle: HBitmap;
54690 DC0, DC2: HDC;
54691 NewHeader: PBitmapInfo;
54692 NewBits: Pointer;
54693 oldHeight, oldWidth, sizeBits, bitsPixel: Integer;
54694 Br: HBrush;
54695 N: Integer;
54696 NewDIBAutoFree: Boolean;
54697 Hndl: THandle;
54698 begin
54699 if Empty then Exit;
54700 NewDIBAutoFree := FALSE;
54701 fDetachCanvas( @Self );
54702 fScanLineSize := 0;
54703 fGetDIBPixels := nil;
54704 fSetDIBPixels := nil;
54706 oldWidth := fWidth;
54707 oldHeight := fHeight;
54708 if fDIBBits <> nil then
54709 begin
54710 oldWidth := fDIBHeader.bmiHeader.biWidth;
54711 oldHeight := Abs(fDIBHeader.bmiHeader.biHeight);
54713 else
54714 if fHandle <> 0 then
54715 begin
54716 if GetObject( fHandle, Sizeof( B ), @ B ) <> 0 then
54717 begin
54718 oldWidth := B.bmWidth;
54719 oldHeight := B.bmHeight;
54720 end;
54721 end;
54723 DC2 := CreateCompatibleDC( 0 );
54725 if fHandleType = bmDDB then
54726 begin
54727 // New HandleType is bmDDB: old bitmap can be copied using Draw method
54728 DC0 := GetDC( 0 );
54729 NewHandle := CreateCompatibleBitmap( DC0, fWidth, fHeight );
54730 ASSERT( NewHandle <> 0, 'Can not create DDB' );
54731 ReleaseDC( 0, DC0 );
54733 oldBmp := SelectObject( DC2, NewHandle );
54734 ASSERT( oldBmp <> 0, 'Can not select bitmap to DC' );
54736 Br := CreateSolidBrush( Color2RGB( fBkColor ) );
54737 FillRect( DC2, MakeRect( 0, 0, fWidth, fHeight ), Br );
54738 DeleteObject( Br );
54740 if fDIBBits <> nil then
54741 begin
54742 SelectObject( DC2, oldBmp );
54743 SetDIBits( DC2, NewHandle, 0, fHeight, fDIBBits, fDIBHeader^, DIB_RGB_COLORS );
54745 else
54746 begin
54747 Draw( DC2, 0, 0 );
54748 SelectObject( DC2, oldBmp );
54749 end;
54751 ClearData; // Image is cleared but fWidth and fHeight are preserved
54752 fHandle := NewHandle;
54754 else
54755 begin
54756 // New format is DIB. GetDIBits applied to transform old data to new one.
54757 bitsPixel := BitCounts[ fNewPixelFormat ];
54758 if bitsPixel = 0 then
54759 begin
54760 bitsPixel := BitCounts[DefaultPixelFormat];
54761 end;
54763 NewHandle := 0;
54764 NewHeader := PrepareBitmapHeader( fWidth, fHeight, bitsPixel );
54765 if fNewPixelFormat = pf16bit then
54766 PreparePF16bit( NewHeader );
54768 sizeBits := CalcScanLineSize( @NewHeader.bmiHeader ) * fHeight;
54770 GetMem( NewBits, sizeBits );
54771 ASSERT( NewBits <> nil, 'No memory' );
54773 Hndl := GetHandle;
54774 if Hndl = 0 then Exit;
54775 N :=
54776 GetDIBits( DC2, Hndl, 0, Min( fHeight, oldHeight ),
54777 NewBits, NewHeader^, DIB_RGB_COLORS );
54778 //Assert( N = Min( fHeight, oldHeight ), 'Can not get all DIB bits' );
54779 if N <> Min( fHeight, oldHeight ) then
54780 begin
54781 FreeMem( NewBits );
54782 NewBits := nil;
54783 NewHandle := CreateDIBSection( DC2, NewHeader^, DIB_RGB_COLORS, NewBits, 0, 0 );
54784 NewDIBAutoFree := TRUE;
54785 ASSERT( NewHandle <> 0, 'Can not create DIB secion for pf16bit bitmap' );
54786 oldBmp := SelectObject( DC2, NewHandle );
54787 ASSERT( oldBmp <> 0, 'Can not select pf16bit to DC' );
54788 Draw( DC2, 0, 0 );
54789 SelectObject( DC2, oldBmp );
54790 end;
54792 ClearData;
54793 fDIBSize := sizeBits;
54794 fDIBBits := NewBits;
54795 fDIBHeader := NewHeader;
54796 fHandle := NewHandle;
54797 fDIBAutoFree := NewDIBAutoFree;
54799 end;
54801 if Assigned( fFillWithBkColor ) then
54802 fFillWithBkColor( @Self, DC2, oldWidth, oldHeight );
54804 DeleteDC( DC2 );
54806 end;
54807 {$ENDIF ASM_VERSION}
54809 {$IFDEF ASM_VERSION}
54810 //[function TBitmap.GetScanLine]
54811 function TBitmap.GetScanLine(Y: Integer): Pointer;
54813 MOV ECX, [EAX].fDIBHeader
54814 JECXZ @@exit
54815 MOV ECX, [ECX].TBitmapInfoHeader.biHeight
54816 TEST ECX, ECX
54817 JL @@1
54819 SUB ECX, EDX
54820 DEC ECX
54821 MOV EDX, ECX
54823 @@1: MOV ECX, [EAX].fScanLineSize
54824 INC ECX
54825 PUSH [EAX].fDIBBits
54826 LOOP @@2
54828 PUSH EDX
54829 CALL GetScanLineSize
54830 POP EDX
54831 XCHG ECX, EAX
54833 @@2: XCHG EAX, ECX
54834 MUL EDX
54835 POP ECX
54836 ADD ECX, EAX
54838 @@exit: XCHG EAX, ECX
54839 end;
54840 {$ELSE ASM_VERSION} //Pascal
54841 function TBitmap.GetScanLine(Y: Integer): Pointer;
54842 begin
54843 ASSERT( (Y >= 0) {and (Y < fHeight)}, 'ScanLine index out of bounds' );
54844 ASSERT( fDIBBits <> nil, 'No bits available' );
54845 Result := nil;
54846 if fDIBHeader = nil then Exit;
54848 if fDIBHeader.bmiHeader.biHeight > 0 then
54849 Y := fHeight - 1 - Y;
54850 if fScanLineSize = 0 then
54851 ScanLineSize;
54853 Result := Pointer( Integer( fDIBBits ) + fScanLineSize * Y );
54854 end;
54855 {$ENDIF ASM_VERSION}
54857 {$IFDEF ASM_VERSION}
54858 //[function TBitmap.GetScanLineSize]
54859 function TBitmap.GetScanLineSize: Integer;
54861 MOV ECX, [EAX].fDIBHeader
54862 JECXZ @@exit
54864 PUSH EAX
54865 XCHG EAX, ECX
54866 CALL CalcScanLineSize
54867 XCHG ECX, EAX
54868 POP EAX
54869 MOV [EAX].fScanLineSize, ECX
54871 @@exit: XCHG EAX, ECX
54872 end;
54873 {$ELSE ASM_VERSION} //Pascal
54874 function TBitmap.GetScanLineSize: Integer;
54875 begin
54876 Result := 0;
54877 if fDIBHeader = nil then Exit;
54878 FScanLineSize := CalcScanLineSize( @fDIBHeader.bmiHeader );
54879 Result := FScanLineSize;
54880 end;
54881 {$ENDIF ASM_VERSION}
54883 {$IFDEF ASM_VERSION}
54884 //[procedure TBitmap.CanvasChanged]
54885 procedure TBitmap.CanvasChanged( Sender : PObj );
54887 PUSH EAX
54889 XCHG EAX, EDX
54890 CALL TCanvas.GetBrush
54891 MOV EDX, [EAX].TGraphicTool.fData.Color
54893 POP EAX
54894 MOV [EAX].fBkColor, EAX
54895 CALL ClearTransImage
54896 end;
54897 {$ELSE ASM_VERSION} //Pascal
54898 procedure TBitmap.CanvasChanged( Sender : PObj );
54899 begin
54900 fBkColor := PCanvas( Sender ).Brush.Color;
54901 ClearTransImage;
54902 end;
54903 {$ENDIF ASM_VERSION}
54905 {$IFDEF ASM_VERSION}
54906 //[procedure TBitmap.Dormant]
54907 procedure TBitmap.Dormant;
54909 PUSH EAX
54910 CALL RemoveCanvas
54911 POP EAX
54912 MOV ECX, [EAX].fHandle
54913 JECXZ @@exit
54914 CALL ReleaseHandle
54915 PUSH EAX
54916 CALL DeleteObject
54917 @@exit:
54918 end;
54919 {$ELSE ASM_VERSION} //Pascal
54920 procedure TBitmap.Dormant;
54921 begin
54922 RemoveCanvas;
54923 if fHandle <> 0 then
54924 DeleteObject( ReleaseHandle );
54925 end;
54926 {$ENDIF ASM_VERSION}
54928 {$IFDEF ASM_VERSION}
54929 //[procedure TBitmap.SetBkColor]
54930 procedure TBitmap.SetBkColor(const Value: TColor);
54932 CMP [EAX].fBkColor, EDX
54933 JE @@exit
54934 MOV [EAX].fBkColor, EDX
54935 MOV [EAX].fFillWithBkColor, offset[FillBmpWithBkColor]
54936 MOV ECX, [EAX].fApplyBkColor2Canvas
54937 JECXZ @@exit
54938 CALL ECX
54939 @@exit:
54940 end;
54941 {$ELSE ASM_VERSION} //Pascal
54942 procedure TBitmap.SetBkColor(const Value: TColor);
54943 begin
54944 if fBkColor = Value then Exit;
54945 fBkColor := Value;
54946 fFillWithBkColor := FillBmpWithBkColor;
54947 if Assigned( fApplyBkColor2Canvas ) then
54948 fApplyBkColor2Canvas( @Self );
54949 end;
54950 {$ENDIF ASM_VERSION}
54952 {$IFDEF ASM_VERSION}
54953 //[function TBitmap.Assign]
54954 function TBitmap.Assign(SrcBmp: PBitmap): Boolean;
54955 const szBIH = sizeof(TBitmapInfoHeader);
54957 PUSHAD
54958 XCHG EBX, EAX
54959 @@clear:
54960 MOV ESI, EDX
54961 MOV EAX, EBX
54962 CALL Clear
54963 MOV EAX, ESI
54964 OR EAX, EAX
54965 JZ @@exit
54966 CALL GetEmpty
54967 JZ @@exit
54968 MOV EAX, [ESI].fWidth
54969 MOV [EBX].fWidth, EAX
54970 MOV EAX, [ESI].fHeight
54971 MOV [EBX].fHeight, EAX
54972 MOVZX ECX, [ESI].fHandleType
54973 MOV [EBX].fHandleType, CL
54974 JECXZ @@fmtDIB
54976 DEC ECX // ECX = 0
54977 PUSH ECX
54978 PUSH ECX
54979 PUSH ECX
54980 PUSH ECX //IMAGE_BITMAP=0
54981 PUSH [ESI].fHandle
54982 CALL CopyImage
54983 MOV [EBX].fHandle, EAX
54984 TEST EAX, EAX
54985 XCHG EDX, EAX
54986 JZ @@clear
54987 JMP @@exit
54989 @@fmtDIB:
54990 XCHG EAX, ECX
54991 MOV AX, szBIH+1024
54992 PUSH EAX
54993 CALL System.@GetMem
54994 MOV [EBX].fDIBHeader, EAX
54995 XCHG EDX, EAX
54996 POP ECX
54997 MOV EAX, [ESI].fDIBHeader
54998 CALL System.Move
54999 MOV EAX, [ESI].fDIBSize
55000 MOV [EBX].fDIBSize, EAX
55001 PUSH EAX
55002 CALL System.@GetMem
55003 MOV [EBX].fDIBBits, EAX
55004 XCHG EDX, EAX
55005 POP ECX
55006 MOV EAX, [ESI].fDIBBits
55007 CALL System.Move
55009 INC EBX // reset "ZF"
55011 @@exit:
55012 POPAD
55013 SETNZ AL
55014 end;
55015 {$ELSE ASM_VERSION} //Pascal
55016 function TBitmap.Assign(SrcBmp: PBitmap): Boolean;
55017 begin
55018 Clear;
55019 Result := False;
55020 if SrcBmp = nil then Exit;
55021 if SrcBmp.Empty then Exit;
55022 fWidth := SrcBmp.fWidth;
55023 fHeight := SrcBmp.fHeight;
55024 fHandleType := SrcBmp.fHandleType;
55025 if SrcBmp.fHandleType = bmDDB then
55026 begin
55027 fHandle := CopyImage( SrcBmp.fHandle, IMAGE_BITMAP, 0, 0, 0 {LR_COPYRETURNORG} );
55028 ASSERT( fHandle <> 0, 'Can not copy bitmap image' );
55029 Result := fHandle <> 0;
55030 if not Result then Clear;
55032 else
55033 begin
55034 GetMem( fDIBHeader, Sizeof(TBitmapInfoHeader) + 256*sizeof(TRGBQuad) );
55035 ASSERT( fDIBHeader <> nil, 'No memory' );
55036 Move( SrcBmp.fDIBHeader^, fDIBHeader^, Sizeof(TBitmapInfoHeader) + 256*sizeof(TRGBQuad) );
55037 fDIBSize := SrcBmp.fDIBSize;
55038 GetMem( fDIBBits, fDIBSize );
55039 ASSERT( fDIBBits <> nil, 'No memory' );
55040 Move( SrcBmp.fDIBBits^, fDIBBits^, fDIBSize );
55041 //fDIBAutoFree := TRUE;
55042 Result := True;
55043 end;
55044 end;
55045 {$ENDIF ASM_VERSION}
55047 {$IFDEF ASM_VERSION}
55048 //[procedure TBitmap.RemoveCanvas]
55049 procedure TBitmap.RemoveCanvas;
55051 PUSH EAX
55052 CALL [EAX].fDetachCanvas
55053 POP EDX
55054 XOR EAX, EAX
55055 XCHG EAX, [EDX].fCanvas
55056 CALL TObj.Free
55057 end;
55058 {$ELSE ASM_VERSION} //Pascal
55059 procedure TBitmap.RemoveCanvas;
55060 begin
55061 fDetachCanvas( @Self );
55062 fCanvas.Free;
55063 fCanvas := nil;
55064 end;
55065 {$ENDIF ASM_VERSION}
55067 {$IFDEF ASM_VERSION}
55068 //[function TBitmap.DIBPalNearestEntry]
55069 function TBitmap.DIBPalNearestEntry(Color: TColor): Integer;
55070 const szBIH = sizeof(TBitmapInfoHeader);
55072 PUSH EBX
55073 PUSH ESI
55074 PUSH EDI
55075 XCHG ESI, EAX
55076 XCHG EAX, EDX
55077 CALL Color2RGBQuad
55078 XCHG EDI, EAX
55079 MOV EAX, ESI
55080 CALL GetDIBPalEntryCount
55081 XCHG ECX, EAX
55082 XOR EAX, EAX
55083 JECXZ @@exit
55085 MOV ESI, [ESI].fDIBHeader
55086 ADD ESI, szBIH
55087 XOR EDX, EDX
55088 PUSH EDX
55089 DEC DX
55091 @@loo: LODSD
55092 XOR EAX, EDI
55093 MOV EBX, EAX
55094 SHR EBX, 16
55095 MOV BH, 0
55096 ADD AL, AH
55097 MOV AH, 0
55098 ADC AX, BX
55099 CMP AX, DX
55100 JAE @@1
55101 MOV DX, AX
55102 POP EBX
55103 PUSH EDX // save better index (in high order word)
55104 @@1: ADD EDX, $10000 // increment index
55105 LOOP @@loo
55107 XCHG EAX, ECX
55108 POP AX
55109 POP AX
55110 @@exit:
55111 POP EDI
55112 POP ESI
55113 POP EBX
55114 end;
55115 {$ELSE ASM_VERSION} //Pascal
55116 function TBitmap.DIBPalNearestEntry(Color: TColor): Integer;
55117 var I, Diff, D: Integer;
55118 C : Integer;
55119 begin
55120 Color := TColor( Color2RGBQuad( Color ) );
55121 Result := 0;
55122 Diff := MaxInt;
55123 for I := 0 to DIBPalEntryCount - 1 do
55124 begin
55125 C := Color xor PInteger( Integer( @fDIBHeader.bmiColors[ 0 ] )
55126 + I * Sizeof( TRGBQuad ) )^;
55127 D := TRGBQuad( C ).rgbBlue + TRGBQuad( C ).rgbGreen + TRGBQuad( C ).rgbRed;
55128 if D < Diff then
55129 begin
55130 Diff := D;
55131 Result := I;
55132 end;
55133 end;
55134 end;
55135 {$ENDIF ASM_VERSION}
55137 {$IFDEF ASM_VERSION}
55138 //[function TBitmap.GetDIBPalEntries]
55139 function TBitmap.GetDIBPalEntries(Idx: Integer): TColor;
55140 const szBIH = sizeof(TBitmapInfoHeader);
55142 MOV ECX, [EAX].fDIBHeader
55143 JECXZ @@exit
55145 MOV ECX, [EAX+szBIH+EDX*4]
55146 INC ECX
55148 @@exit: DEC ECX
55149 XCHG EAX, ECX
55150 end;
55151 {$ELSE ASM_VERSION} //Pascal
55152 function TBitmap.GetDIBPalEntries(Idx: Integer): TColor;
55153 begin
55154 Result := TColor(-1);
55155 if fDIBBits = nil then Exit;
55156 ASSERT( PixelFormat in [pf1bit..pf8bit], 'Format has no DIB palette entries available' );
55157 ASSERT( (Idx >= 0) and (Idx < (1 shl fDIBHeader.bmiHeader.biBitCount)),
55158 'DIB palette index out of bounds' );
55159 Result := PDWORD( Integer( @fDIBHeader.bmiColors[ 0 ] )
55160 + Idx * Sizeof( TRGBQuad ) )^;
55161 end;
55162 {$ENDIF ASM_VERSION}
55164 {$IFDEF ASM_VERSION}
55165 //[function TBitmap.GetDIBPalEntryCount]
55166 function TBitmap.GetDIBPalEntryCount: Integer;
55168 PUSH EAX
55169 CALL GetEmpty
55170 POP EAX
55171 JZ @@ret0
55172 CALL GetPixelFormat
55173 MOVZX ECX, AL
55174 MOV EAX, ECX
55175 LOOP @@1
55176 // pf1bit:
55177 INC EAX
55179 @@1:
55180 LOOP @@2
55181 // pf4bit:
55182 MOV AL, 16
55184 @@2:
55185 LOOP @@ret0
55186 // pf8bit:
55187 XOR EAX, EAX
55188 INC AH
55190 @@ret0:
55191 XOR EAX, EAX
55192 end;
55193 {$ELSE ASM_VERSION} //Pascal
55194 function TBitmap.GetDIBPalEntryCount: Integer;
55195 begin
55196 Result := 0;
55197 if Empty then Exit;
55198 case PixelFormat of
55199 pf1bit: Result := 2;
55200 pf4bit: Result := 16;
55201 pf8bit: Result := 256;
55202 else;
55203 end;
55204 end;
55205 {$ENDIF ASM_VERSION}
55207 //[procedure TBitmap.SetDIBPalEntries]
55208 procedure TBitmap.SetDIBPalEntries(Idx: Integer; const Value: TColor);
55209 begin
55210 if fDIBBits = nil then Exit;
55211 Dormant;
55212 PDWORD( Integer( @fDIBHeader.bmiColors[ 0 ] )
55213 + Idx * Sizeof( TRGBQuad ) )^ := Color2RGB( Value );
55214 end;
55216 //[procedure TBitmap.SetHandleType]
55217 procedure TBitmap.SetHandleType(const Value: TBitmapHandleType);
55218 {var B: tagBitmap;
55219 DC0: HDC;}
55220 begin
55221 if fHandleType = Value then Exit;
55222 //++++++++++++++++ ?????????
55223 {if fHandleType = bmDDB then
55224 if PixelFormat = pfDevice then
55225 begin
55226 DC0 := GetDC( 0 );
55227 fNewPixelFormat := Bits2PixelFormat( GetDeviceCaps( DC0, BITSPIXEL ) );
55228 ReleaseDC( 0, DC0 );
55230 else
55231 if FHandle <> 0 then
55232 begin
55233 if GetObject( FHandle, Sizeof( B ), @ B ) > 0 then
55234 fNewPixelFormat := Bits2PixelFormat( B.bmPlanes * B.bmBitsPixel );
55235 end;}
55236 //----------------
55237 fHandleType := Value;
55238 FormatChanged;
55239 end;
55241 //[function TBitmap.GetPixelFormat]
55242 function TBitmap.GetPixelFormat: TPixelFormat;
55243 begin
55244 if (HandleType = bmDDB) or (fDIBBits = nil) then
55245 Result := pfDevice
55246 else
55247 begin
55248 Result := Bits2PixelFormat( fDIBHeader.bmiHeader.biBitCount );
55249 if (Result = pf15bit) and (fDIBHeader.bmiHeader.biCompression <> 0) then
55250 begin
55251 Assert( fDIBHeader.bmiHeader.biCompression = BI_BITFIELDS, 'Unsupported bitmap format' );
55252 Result := pf16bit;
55253 end;
55254 end;
55255 end;
55257 {$IFDEF ASM_VERSION}
55258 //[procedure TBitmap.ClearTransImage]
55259 procedure TBitmap.ClearTransImage;
55261 OR [EAX].fTransColor, -1
55262 XOR EDX, EDX
55263 XCHG [EAX].fTransMaskBmp, EDX
55264 XCHG EAX, EDX
55265 CALL TObj.Free
55266 end;
55267 {$ELSE ASM_VERSION} //Pascal
55268 procedure TBitmap.ClearTransImage;
55269 begin
55270 fTransColor := clNone;
55271 fTransMaskBmp.Free;
55272 fTransMaskBmp := nil;
55273 end;
55274 {$ENDIF ASM_VERSION}
55276 {$IFDEF ASM_VERSION}
55277 //[procedure TBitmap.Convert2Mask]
55278 procedure TBitmap.Convert2Mask(TranspColor: TColor);
55280 PUSH EBX
55281 PUSH ESI
55282 MOV EBX, EAX
55283 MOV ESI, EDX
55284 CALL GetHandle
55285 TEST EAX, EAX
55286 JZ @@exit
55288 PUSH 0
55289 PUSH 1
55290 PUSH 1
55291 PUSH [EBX].fHeight
55292 PUSH [EBX].fWidth
55293 CALL CreateBitmap
55294 PUSH EAX // MonoHandle
55295 PUSH 0
55296 CALL CreateCompatibleDC
55297 POP EDX
55298 PUSH EDX
55299 PUSH EAX // MonoDC
55301 PUSH EDX
55302 PUSH EAX
55303 CALL SelectObject
55304 PUSH EAX // SaveMono
55306 CALL StartDC // DCfrom, SaveFrom
55307 XCHG EAX, ESI
55308 CALL Color2RGB
55309 PUSH EAX // Color2RGB(TranspColor)
55310 PUSH dword ptr [ESP+8] //DCfrom
55311 CALL Windows.SetBkColor
55312 PUSH EAX // SaveBkColor
55314 PUSH SRCCOPY
55315 PUSH 0
55316 PUSH 0
55317 PUSH dword ptr [ESP+12+4+4] //DCfrom
55318 PUSH [EBX].fHeight
55319 PUSH [EBX].fWidth
55320 PUSH 0
55321 PUSH 0
55322 PUSH dword ptr [ESP+32+16] //MonoDC
55323 CALL BitBlt
55325 PUSH dword ptr [ESP+8] //DCfrom
55326 CALL Windows.SetBkColor // ESP-> SaveFrom
55327 CALL FinishDC // ESP-> SaveMono
55328 CALL FinishDC // ESP-> MonoHandle
55330 MOV EAX, EBX
55331 CALL ClearData
55332 POP [EBX].fHandle
55333 MOV [EBX].fHandleType, bmDDB
55334 @@exit:
55335 POP ESI
55336 POP EBX
55337 end;
55338 {$ELSE ASM_VERSION} //Pascal
55339 procedure TBitmap.Convert2Mask(TranspColor: TColor);
55340 var MonoHandle: HBitmap;
55341 SaveMono, SaveFrom: THandle;
55342 MonoDC, {DC0,} DCfrom: HDC;
55343 SaveBkColor: TColorRef;
55344 begin
55345 if GetHandle = 0 then Exit;
55346 fDetachCanvas( @Self );
55347 ///DC0 := GetDC( 0 );
55348 MonoHandle := CreateBitmap( fWidth, fHeight, 1, 1, nil );
55349 ASSERT( MonoHandle <> 0, 'Can not create monochrome bitmap' );
55350 MonoDC := CreateCompatibleDC( 0 );
55351 SaveMono := SelectObject( MonoDC, MonoHandle );
55352 ASSERT( SaveMono <> 0, 'Can not select bitmap to DC' );
55353 DCfrom := CreateCompatibleDC( 0 );
55354 SaveFrom := SelectObject( DCfrom, fHandle );
55355 ASSERT( SaveFrom <> 0, 'Can not select source bitmap to DC' );
55356 TranspColor := Color2RGB( TranspColor );
55357 SaveBkColor := Windows.SetBkColor( DCfrom, TranspColor );
55358 BitBlt( MonoDC, 0, 0, fWidth, fHeight, DCfrom, 0, 0, SRCCOPY );
55359 {$IFDEF CHK_BITBLT} Chk_BitBlt; {$ENDIF}
55360 Windows.SetBkColor( DCfrom, SaveBkColor );
55361 SelectObject( DCfrom, SaveFrom );
55362 DeleteDC( DCfrom );
55363 SelectObject( MonoDC, SaveMono );
55364 DeleteDC( MonoDC );
55365 ///ReleaseDC( 0, DC0 );
55366 ClearData;
55367 fHandle := MonoHandle;
55368 fHandleType := bmDDB;
55369 end;
55370 {$ENDIF ASM_VERSION}
55372 //[procedure TBitmap.Invert]
55373 procedure TBitmap.Invert;
55374 begin
55375 //BitBlt( Canvas.Handle, 0, 0, Width, Height, Canvas.Handle, 0, 0, DSTINVERT )
55376 InvertRect(Canvas.Handle, BoundsRect);
55377 end;
55379 //[procedure TBitmap.DIBDrawRect]
55380 procedure TBitmap.DIBDrawRect( DC: HDC; X, Y: Integer; const R: TRect );
55381 begin
55382 if fDIBBits = nil then Exit;
55383 StretchDIBits( DC, X, Y, R.Right - R.Left, R.Bottom - R.Top,
55384 R.Left, fHeight - R.Bottom, R.Right - R.Left, R.Bottom - R.Top,
55385 fDIBBits, fDIBHeader^, DIB_RGB_COLORS, SRCCOPY );
55386 end;
55388 //[PROCEDURE _PrepareBmp2Rotate]
55389 {$IFDEF ASM_VERSION}
55390 procedure _PrepareBmp2Rotate;
55391 const szBIH = sizeof(TBitmapInfoHeader);
55393 { <- BL = increment to height }
55394 XCHG EDI, EAX
55395 MOV ESI, EDX // ESI = SrcBmp
55397 XCHG EAX, EDX
55398 CALL TBitmap.GetPixelFormat
55399 MOVZX ECX, AL
55400 PUSH ECX
55402 MOV EDX, [ESI].TBitmap.fWidth
55403 MOVZX EBX, BL
55404 ADD EDX, EBX
55406 MOV EAX, [ESI].TBitmap.fHeight
55407 CALL NewDIBBitmap
55408 STOSD
55409 XCHG EDI, EAX
55411 MOV EAX, [ESI].TBitmap.fDIBHeader
55412 ADD EAX, szBIH
55413 MOV EDX, [EDI].TBitmap.fDIBHeader
55414 ADD EDX, szBIH
55415 XOR ECX, ECX
55416 MOV CH, 4
55417 CALL System.Move
55419 MOV EAX, EDI
55420 XOR EDX, EDX
55421 CALL TBitmap.GetScanLine
55422 MOV EBX, [EDI].TBitmap.fWidth
55423 DEC EBX // EBX = DstBmp.fWidth - 1
55424 XCHG EDI, EAX // EDI = DstBmp.ScanLine[ 0 ]
55426 XOR EDX, EDX
55427 INC EDX
55428 CALL TBitmap.GetScanLine
55429 XCHG EDX, EAX
55430 SUB EDX, EDI // EDX = BytesPerDstLine
55432 MOV EBP, [ESI].TBitmap.fWidth
55433 DEC EBP // EBP = SrcBmp.fWidth - 1
55435 POP ECX // ECX = PixelFormat
55436 end;
55437 {$ENDIF ASM_VERSION}
55438 //[END _PrepareBmp2Rotate]
55440 //[PROCEDURE _RotateBitmapMono]
55441 {$IFDEF ASM_VERSION}
55442 procedure _RotateBitmapMono( var DstBmp: PBitmap; SrcBmp: PBitmap );
55443 const szBIH = sizeof(TBitmapInfoHeader);
55445 PUSHAD
55446 MOV BL, 7
55447 CALL _PrepareBmp2Rotate
55449 SHR EBP, 3
55450 SHL EBP, 8 // EBP = (WBytes-1) * 256
55452 MOV ECX, EBX // ECX and 7 = Shf
55453 SHR EBX, 3
55454 ADD EDI, EBX // EDI = Dst
55456 XOR EBX, EBX // EBX = temp mask
55457 XOR EAX, EAX // Y = 0
55458 @@looY:
55459 PUSH EAX
55460 PUSH EDI // Dst1 = Dst (Dst1 in EDI, Dst saved)
55461 PUSH ESI // SrcBmp
55463 PUSH EDX //BytesPerDstLine
55464 PUSH ECX //Shf
55466 XCHG EDX, EAX
55467 XCHG EAX, ESI
55468 CALL TBitmap.GetScanLine
55469 XCHG ESI, EAX // ESI = Src
55471 POP ECX // CL = Shf
55472 AND ECX, 7 // ECX = Shf
55473 OR ECX, EBP // ECX = (Wbytes-1)*8 + Shf
55474 POP EDX // EDX = BytesPerDstLine
55476 MOV BH, $80
55477 SHR EBX, CL // BH = mask, BL = mask & Tmp
55478 @@looX:
55479 XOR EAX, EAX
55481 LODSB
55483 MOV AH, AL
55484 SHR EAX, CL
55485 OR EAX,$01000000
55487 @@looBits:
55488 MOV BL, AH
55489 AND BL, BH
55490 OR [EDI], BL
55491 ADD EDI, EDX
55492 ADD EAX, EAX
55493 JNC @@looBits
55495 SUB ECX, 256
55496 JGE @@looX
55498 POP ESI // ESI = SrcBmp
55499 POP EDI // EDI = Dst
55500 POP EAX // EAX = Y
55502 ADD ECX, 256-1
55503 JGE @@1
55504 DEC EDI
55505 @@1:
55506 INC EAX
55507 CMP EAX, [ESI].TBitmap.fHeight
55508 JL @@looY
55510 POPAD
55511 end;
55512 {$ELSE ASM_VERSION} //Pascal
55513 procedure _RotateBitmapMono( var DstBmp: PBitmap; SrcBmp: PBitmap );
55514 var X, Y, Z, Shf, Wbytes, BytesPerDstLine: Integer;
55515 Src, Dst, Dst1: PByte;
55516 Tmp: Byte;
55517 begin
55519 DstBmp := NewDIBBitmap( SrcBmp.fHeight, (SrcBmp.fWidth + 7) and not 7, pf1bit );
55520 Move( SrcBmp.fDIBHeader.bmiColors[ 0 ], DstBmp.fDIBHeader.bmiColors[ 0 ], 2 * Sizeof( TRGBQuad ) );
55522 // Calculate ones:
55523 Dst := DstBmp.ScanLine[ 0 ];
55524 BytesPerDstLine := Integer( DstBmp.ScanLine[ 1 ]) - Integer( Dst );
55525 Wbytes := (SrcBmp.fWidth + 7) shr 3;
55527 Inc( Dst, (DstBmp.fWidth - 1) shr 3 );
55528 Shf := (DstBmp.fWidth - 1) and 7;
55530 // Rotating bits:
55531 for Y := 0 to SrcBmp.fHeight - 1 do
55532 begin
55533 Src := SrcBmp.ScanLine[ Y ];
55534 Dst1 := Dst;
55535 for X := Wbytes downto 1 do
55536 begin
55537 Tmp := Src^;
55538 Inc( Src );
55539 for Z := 8 downto 1 do
55540 begin
55541 Dst1^ := Dst1^ or ( (Tmp and $80) shr Shf );
55542 Tmp := Tmp shl 1;
55543 Inc( Dst1, BytesPerDstLine );
55544 end;
55545 end;
55546 Dec( Shf );
55547 if Shf < 0 then
55548 begin
55549 Shf := 7;
55550 Dec( Dst );
55551 end;
55552 end;
55553 end;
55554 {$ENDIF ASM_VERSION}
55555 //[END _RotateBitmapMono]
55557 //[PROCEDURE _RotateBitmap4bit]
55558 {$IFDEF ASM_VERSION}
55559 procedure _RotateBitmap4bit( var DstBmp: PBitmap; SrcBmp: PBitmap );
55560 const szBIH = sizeof(TBitmapInfoHeader);
55562 PUSHAD
55563 MOV BL, 1
55564 CALL _PrepareBmp2Rotate
55566 SHR EBP, 1 // EBP = WBytes - 1
55567 SHL EBP, 8 // EBP = (WBytes - 1) * 256
55569 // EBX = DstBmp.fWidth - 1
55570 MOV ECX, EBX
55571 SHL ECX, 2 // ECX and 7 = Shf (0 or 4)
55572 SHR EBX, 1
55573 ADD EDI, EBX // EDI = Dst
55575 XOR EAX, EAX // Y = 0
55576 XOR EBX, EBX
55578 @@looY:
55579 PUSH EAX // save Y
55580 PUSH EDI // Dst1 = Dst (Dst1 in EDI, Dst saved)
55581 PUSH ESI // SrcBmp
55583 PUSH EDX // BytesPerDstLine
55584 PUSH ECX // Shf
55586 XCHG EDX, EAX
55587 XCHG EAX, ESI
55588 CALL TBitmap.GetScanLine
55589 XCHG ESI, EAX // ESI = Src
55591 POP ECX
55592 AND ECX, 7 // CL = Shf
55593 OR ECX, EBP // ECX = (WBytes-1)*256 + Shf
55594 POP EDX // EDX = BytesPerDstLine
55596 MOV BH, $F0
55597 SHR EBX, CL // shift mask right 4 or 0
55599 @@looX:
55600 XOR EAX, EAX
55601 LODSB
55602 MOV AH, AL
55603 SHR EAX, CL
55605 MOV BL, AH
55606 AND BL, BH
55607 OR [EDI], BL
55608 ADD EDI, EDX
55610 SHL EAX, 4
55611 AND AH, BH
55612 OR [EDI], AH
55613 ADD EDI, EDX
55615 SUB ECX, 256
55616 JGE @@looX
55618 POP ESI // ESI = SrcBmp
55619 POP EDI // EDI = Dst
55620 POP EAX // EAX = Y
55622 ADD ECX, 256 - 4
55623 JGE @@1
55625 DEC EDI
55626 @@1:
55627 INC EAX
55628 CMP EAX, [ESI].TBitmap.fHeight
55629 JL @@looY
55631 POPAD
55632 end;
55633 {$ELSE ASM_VERSION} //Pascal
55634 procedure _RotateBitmap4bit( var DstBmp: PBitmap; SrcBmp: PBitmap );
55635 var X, Y, Shf, Wbytes, BytesPerDstLine: Integer;
55636 Src, Dst, Dst1: PByte;
55637 Tmp: Byte;
55638 begin
55640 DstBmp := NewDIBBitmap( SrcBmp.fHeight, (SrcBmp.fWidth + 1) and not 1, pf4bit );
55641 Move( SrcBmp.fDIBHeader.bmiColors[ 0 ], DstBmp.fDIBHeader.bmiColors[ 0 ], 16 * Sizeof( TRGBQuad ) );
55643 // Calculate ones:
55644 Dst := DstBmp.ScanLine[ 0 ];
55645 BytesPerDstLine := Integer( DstBmp.ScanLine[ 1 ]) - Integer( Dst );
55646 Wbytes := (SrcBmp.fWidth + 1) shr 1;
55648 Inc( Dst, (DstBmp.fWidth - 1) shr 1 );
55649 Shf := ((DstBmp.fWidth - 1) and 1) shl 2;
55651 // Rotating bits:
55652 for Y := 0 to SrcBmp.fHeight - 1 do
55653 begin
55654 Src := SrcBmp.ScanLine[ Y ];
55655 Dst1 := Dst;
55656 for X := Wbytes downto 1 do
55657 begin
55658 Tmp := Src^;
55659 Inc( Src );
55660 Dst1^ := Dst1^ or ( (Tmp and $F0) shr Shf );
55661 Inc( Dst1, BytesPerDstLine );
55662 Dst1^ := Dst1^ or ( ((Tmp shl 4) and $F0) shr Shf );
55663 Inc( Dst1, BytesPerDstLine );
55664 end;
55665 Dec( Shf, 4 );
55666 if Shf < 0 then
55667 begin
55668 Shf := 4;
55669 Dec( Dst );
55670 end;
55671 end;
55672 end;
55673 {$ENDIF ASM_VERSION}
55674 //[END _RotateBitmap4bit]
55676 //[PROCEDURE _RotateBitmap8bit]
55677 {$IFDEF ASM_VERSION}
55678 procedure _RotateBitmap8bit( var DstBmp: PBitmap; SrcBmp: PBitmap );
55679 const szBIH = sizeof(TBitmapInfoHeader);
55681 PUSHAD
55682 XOR EBX, EBX
55683 CALL _PrepareBmp2Rotate
55685 ADD EDI, EBX // EDI = Dst
55687 MOV EBX, EDX // EBX = BytesPerDstLine
55688 DEC EBX
55689 MOV EBP, ESI // EBP = SrcBmp
55691 XOR EDX, EDX // Y = 0
55693 @@looY:
55694 PUSH EDX
55695 PUSH EDI
55697 MOV EAX, EBP
55698 CALL TBitmap.GetScanLine
55699 XCHG ESI, EAX
55700 MOV ECX, [EBP].TBitmap.fWidth
55702 @@looX:
55703 MOVSB
55704 ADD EDI, EBX
55705 LOOP @@looX
55707 POP EDI
55708 POP EDX
55710 DEC EDI
55711 INC EDX
55712 CMP EDX, [EBP].TBitmap.fHeight
55713 JL @@looY
55715 POPAD
55716 end;
55717 {$ELSE ASM_VERSION} //Pascal
55718 procedure _RotateBitmap8bit( var DstBmp: PBitmap; SrcBmp: PBitmap );
55719 var X, Y, Wbytes, BytesPerDstLine: Integer;
55720 Src, Dst, Dst1: PByte;
55721 Tmp: Byte;
55722 begin
55724 DstBmp := NewDIBBitmap( SrcBmp.fHeight, SrcBmp.fWidth, SrcBmp.PixelFormat );
55725 Move( SrcBmp.fDIBHeader.bmiColors[ 0 ], DstBmp.fDIBHeader.bmiColors[ 0 ], 256 * Sizeof( TRGBQuad ) );
55727 // Calculate ones:
55728 Wbytes := SrcBmp.fWidth;
55729 Dst := DstBmp.ScanLine[ 0 ];
55730 BytesPerDstLine := Integer( DstBmp.ScanLine[ 1 ]) - Integer( Dst );
55732 Inc( Dst, DstBmp.fWidth - 1 );
55734 // Rotating bits:
55735 for Y := 0 to SrcBmp.fHeight - 1 do
55736 begin
55737 Src := SrcBmp.ScanLine[ Y ];
55738 Dst1 := Dst;
55739 for X := Wbytes downto 1 do
55740 begin
55741 Tmp := Src^;
55742 Inc( Src );
55743 Dst1^ := Tmp;
55744 Inc( Dst1, BytesPerDstLine );
55745 end;
55746 Dec( Dst );
55747 end;
55749 end;
55750 {$ENDIF ASM_VERSION}
55751 //[END _RotateBitmap8bit]
55753 //[PROCEDURE _RotateBitmap16bit]
55754 {$IFDEF ASM_VERSION}
55755 procedure _RotateBitmap16bit( var DstBmp: PBitmap; SrcBmp: PBitmap );
55757 PUSHAD
55758 XOR EBX, EBX
55759 CALL _PrepareBmp2Rotate
55761 ADD EBX, EBX
55762 ADD EDI, EBX // EDI = Dst
55763 MOV EBX, EDX // EBX = BytesPerDstLine
55764 DEC EBX
55765 DEC EBX
55766 MOV EBP, ESI // EBP = SrcBmp
55768 XOR EDX, EDX // Y = 0
55770 @@looY:
55771 PUSH EDX
55772 PUSH EDI
55774 MOV EAX, EBP
55775 CALL TBitmap.GetScanLine
55776 XCHG ESI, EAX
55777 MOV ECX, [EBP].TBitmap.fWidth
55779 @@looX:
55780 MOVSW
55781 ADD EDI, EBX
55782 LOOP @@looX
55784 POP EDI
55785 POP EDX
55787 DEC EDI
55788 DEC EDI
55789 INC EDX
55790 CMP EDX, [EBP].TBitmap.fHeight
55791 JL @@looY
55793 POPAD
55794 end;
55795 {$ELSE ASM_VERSION} //Pascal
55796 procedure _RotateBitmap16bit( var DstBmp: PBitmap; SrcBmp: PBitmap );
55797 var X, Y, Wwords, BytesPerDstLine: Integer;
55798 Src, Dst, Dst1: PWord;
55799 Tmp: Word;
55800 begin
55802 DstBmp := NewDIBBitmap( SrcBmp.fHeight, SrcBmp.fWidth, SrcBmp.PixelFormat );
55804 // Calculate ones:
55805 Wwords := SrcBmp.fWidth;
55806 Dst := DstBmp.ScanLine[ 0 ];
55807 BytesPerDstLine := Integer( DstBmp.ScanLine[ 1 ]) - Integer( Dst );
55809 Inc( Dst, DstBmp.fWidth - 1 );
55811 // Rotating bits:
55812 for Y := 0 to SrcBmp.fHeight - 1 do
55813 begin
55814 Src := SrcBmp.ScanLine[ Y ];
55815 Dst1 := Dst;
55816 for X := Wwords downto 1 do
55817 begin
55818 Tmp := Src^;
55819 Inc( Src );
55820 Dst1^ := Tmp;
55821 Inc( PByte(Dst1), BytesPerDstLine );
55822 end;
55823 Dec( Dst );
55824 end;
55826 end;
55827 {$ENDIF ASM_VERSION}
55828 //[END _RotateBitmap16bit]
55830 //[PROCEDURE _RotateBitmap2432bit]
55831 {$IFDEF ASM_VERSION}
55832 procedure _RotateBitmap2432bit( var DstBmp: PBitmap; SrcBmp: PBitmap );
55834 PUSHAD
55835 XOR EBX, EBX
55836 CALL _PrepareBmp2Rotate
55838 SUB ECX, pf24bit
55839 JNZ @@10
55840 LEA EBX, [EBX+EBX*2]
55841 JMP @@11
55842 @@10:
55843 LEA EBX, [EBX*4]
55844 @@11: ADD EDI, EBX // EDI = Dst
55846 MOV EBX, EDX // EBX = BytesPerDstLine
55847 DEC EBX
55848 DEC EBX
55849 DEC EBX
55851 MOV EBP, ESI // EBP = SrcBmp
55853 XOR EDX, EDX // Y = 0
55855 @@looY:
55856 PUSH EDX
55857 PUSH EDI
55858 PUSH ECX // ECX = 0 if pf24bit (1 if pf32bit)
55860 MOV EAX, EBP
55861 CALL TBitmap.GetScanLine
55862 XCHG ESI, EAX
55863 MOV ECX, [EBP].TBitmap.fWidth
55864 POP EAX
55865 PUSH EAX
55867 @@looX:
55868 MOVSW
55869 MOVSB
55870 ADD ESI, EAX
55871 ADD EDI, EBX
55872 LOOP @@looX
55874 POP ECX
55875 POP EDI
55876 POP EDX
55878 DEC EDI
55879 DEC EDI
55880 DEC EDI
55881 SUB EDI, ECX
55882 INC EDX
55883 CMP EDX, [EBP].TBitmap.fHeight
55884 JL @@looY
55886 POPAD
55887 end;
55888 {$ELSE ASM_VERSION} //Pascal
55889 procedure _RotateBitmap2432bit( var DstBmp: PBitmap; SrcBmp: PBitmap );
55890 var X, Y, Wwords, BytesPerDstLine, IncW: Integer;
55891 Src, Dst, Dst1: PDWord;
55892 Tmp: DWord;
55893 begin
55895 DstBmp := NewDIBBitmap( SrcBmp.fHeight, SrcBmp.fWidth, SrcBmp.PixelFormat );
55897 // Calculate ones:
55898 IncW := 4;
55899 if DstBmp.PixelFormat = pf24bit then
55900 IncW := 3;
55901 Wwords := SrcBmp.fWidth;
55902 Dst := DstBmp.ScanLine[ 0 ];
55903 BytesPerDstLine := Integer( DstBmp.ScanLine[ 1 ]) - Integer( Dst );
55905 Inc( PByte(Dst), (DstBmp.fWidth - 1) * IncW );
55907 // Rotating bits:
55908 for Y := 0 to SrcBmp.fHeight - 1 do
55909 begin
55910 Src := SrcBmp.ScanLine[ Y ];
55911 Dst1 := Dst;
55912 for X := Wwords downto 1 do
55913 begin
55914 Tmp := Src^ and $FFFFFF;
55915 Inc( PByte(Src), IncW );
55916 Dst1^ := Dst1^ or Tmp;
55917 Inc( PByte(Dst1), BytesPerDstLine );
55918 end;
55919 Dec( PByte(Dst), IncW );
55920 end;
55922 end;
55923 {$ENDIF ASM_VERSION}
55924 //[END _RotateBitmap2432bit]
55926 type
55927 TRotateBmpRefs = packed record
55928 proc_RotateBitmapMono: procedure( var Dst: PBitmap; Src: PBitmap );
55929 proc_RotateBitmap4bit: procedure( var Dst: PBitmap; Src: PBitmap );
55930 proc_RotateBitmap8bit: procedure( var Dst: PBitmap; Src: PBitmap );
55931 proc_RotateBitmap16bit: procedure( var Dst: PBitmap; Src: PBitmap );
55932 proc_RotateBitmap2432bit: procedure( var Dst: PBitmap; Src: PBitmap );
55933 end;
55936 RotateProcs: TRotateBmpRefs;
55938 //[PROCEDURE _RotateBitmapRight]
55939 {$IFDEF ASM_VERSION}
55940 procedure _RotateBitmapRight( SrcBmp: PBitmap );
55942 PUSH EBX
55943 PUSH EDI
55944 MOV EBX, EAX
55945 CMP [EBX].TBitmap.fHandleType, bmDIB
55946 JNZ @@exit
55948 CALL TBitmap.GetPixelFormat
55949 MOVZX ECX, AL
55950 LOOP @@not1bit
55951 MOV EAX, [RotateProcs.proc_RotateBitmapMono]
55952 @@not1bit:
55953 LOOP @@not4bit
55954 MOV EAX, [RotateProcs.proc_RotateBitmap4bit]
55955 @@not4bit:
55956 LOOP @@not8bit
55957 MOV EAX, [RotateProcs.proc_RotateBitmap8bit]
55958 @@not8bit:
55959 LOOP @@not15bit
55960 INC ECX
55961 @@not15bit:
55962 LOOP @@not16bit
55963 MOV EAX, [RotateProcs.proc_RotateBitmap16bit]
55964 @@not16bit:
55965 LOOP @@not24bit
55966 INC ECX
55967 @@not24bit:
55968 LOOP @@not32bit
55969 MOV EAX, [RotateProcs.proc_RotateBitmap2432bit]
55970 @@not32bit:
55971 TEST EAX, EAX
55972 JZ @@exit
55974 PUSH ECX
55975 XCHG ECX, EAX
55976 MOV EAX, ESP
55977 MOV EDX, EBX
55978 CALL ECX
55980 POP EDI
55981 MOV EAX, [EBX].TBitmap.fWidth
55982 CMP EAX, [EDI].TBitmap.fHeight
55983 JGE @@noCutHeight
55985 MOV EDX, [EDI].TBitmap.fScanLineSize
55986 MUL EDX
55987 MOV [EDI].TBitmap.fDIBSize, EAX
55989 MOV EDX, [EDI].TBitmap.fDIBHeader
55990 MOV EDX, [EDX].TBitmapInfoHeader.biHeight
55991 TEST EDX, EDX
55992 JL @@noCorrectImg
55994 PUSH EAX
55996 MOV EDX, [EDI].TBitmap.fHeight
55997 DEC EDX
55998 MOV EAX, EDI
55999 CALL TBitmap.GetScanLine
56000 PUSH EAX
56002 MOV EDX, [EBX].TBitmap.fWidth
56003 DEC EDX
56004 MOV EAX, EDI
56005 CALL TBitmap.GetScanLine
56006 POP EDX
56008 POP ECX
56009 CALL System.Move
56011 @@noCorrectImg:
56012 MOV EAX, [EBX].TBitmap.fWidth
56013 MOV [EDI].TBitmap.fHeight, EAX
56014 MOV EDX, [EDI].TBitmap.fDIBHeader
56015 MOV [EDX].TBitmapInfoHeader.biHeight, EAX
56017 @@noCutHeight:
56018 MOV EAX, EBX
56019 CALL TBitmap.ClearData
56021 XOR EAX, EAX
56022 XCHG EAX, [EDI].TBitmap.fDIBHeader
56023 XCHG [EBX].TBitmap.fDIBHeader, EAX
56025 XCHG EAX, [EDI].TBitmap.fDIBBits
56026 XCHG [EBX].TBitmap.fDIBBits, EAX
56028 MOV AL, [EDI].TBitmap.fDIBAutoFree
56029 MOV [EBX].TBitmap.fDIBAutoFree, AL
56031 MOV EAX, [EDI].TBitmap.fDIBSize
56032 MOV [EBX].TBitmap.fDIBSize, EAX
56034 MOV EAX, [EDI].TBitmap.fWidth
56035 MOV [EBX].TBitmap.fWidth, EAX
56037 MOV EAX, [EDI].TBitmap.fHeight
56038 MOV [EBX].TBitmap.fHeight, EAX
56040 XCHG EAX, EDI
56041 CALL TObj.Free
56042 @@exit:
56043 POP EDI
56044 POP EBX
56045 end;
56046 {$ELSE ASM_VERSION} //Pascal
56047 procedure _RotateBitmapRight( SrcBmp: PBitmap );
56048 var DstBmp: PBitmap;
56049 RotateProc: procedure( var DstBmp: PBitmap; SrcBmp: PBitmap );
56050 begin
56051 if SrcBmp.fHandleType <> bmDIB then Exit;
56053 case SrcBmp.PixelFormat of
56054 pf1bit: RotateProc := RotateProcs.proc_RotateBitmapMono;
56055 pf4bit: RotateProc := RotateProcs.proc_RotateBitmap4bit;
56056 pf8bit: RotateProc := RotateProcs.proc_RotateBitmap8bit;
56057 pf15bit, pf16bit: RotateProc := RotateProcs.proc_RotateBitmap16bit;
56058 else RotateProc := RotateProcs.proc_RotateBitmap2432bit;
56059 end;
56061 if not Assigned( RotateProc ) then Exit;
56062 RotateProc( DstBmp, SrcBmp );
56064 if DstBmp.fHeight > SrcBmp.fWidth then
56065 begin
56066 DstBmp.fDIBSize := DstBmp.fScanLineSize * SrcBmp.fWidth;
56067 //if DWORD( DstBmp.ScanLine[ 0 ] ) > DWORD( DstBmp.ScanLine[ 1 ] ) then
56068 if DstBmp.fDIBHeader.bmiHeader.biHeight > 0 then
56069 Move( DstBmp.ScanLine[ SrcBmp.fWidth - 1 ]^, DstBmp.ScanLine[ DstBmp.fHeight - 1 ]^,
56070 DstBmp.fDIBSize );
56071 DstBmp.fHeight := SrcBmp.fWidth;
56072 DstBmp.fDIBHeader.bmiHeader.biHeight := DstBmp.fHeight;
56073 end;
56075 SrcBmp.ClearData;
56077 //SrcBmp.fNewPixelFormat := DstBmp.PixelFormat;
56078 SrcBmp.fDIBHeader := DstBmp.fDIBHeader;
56079 DstBmp.fDIBHeader := nil;
56081 SrcBmp.fDIBBits := DstBmp.fDIBBits;
56082 DstBmp.fDIBBits := nil;
56083 SrcBmp.fDIBAutoFree := DstBmp.fDIBAutoFree;
56085 SrcBmp.fDIBSize := DstBmp.fDIBSize;
56087 SrcBmp.fWidth := DstBmp.fWidth;
56088 SrcBmp.fHeight := DstBmp.fHeight;
56089 DstBmp.Free;
56090 end;
56091 {$ENDIF ASM_VERSION}
56092 //[END _RotateBitmapRight]
56094 //[procedure TBitmap.RotateRight]
56095 procedure TBitmap.RotateRight;
56096 const AllRotators: TRotateBmpRefs = (
56097 proc_RotateBitmapMono: _RotateBitmapMono;
56098 proc_RotateBitmap4bit: _RotateBitmap4bit;
56099 proc_RotateBitmap8bit: _RotateBitmap8bit;
56100 proc_RotateBitmap16bit: _RotateBitmap16bit;
56101 proc_RotateBitmap2432bit: _RotateBitmap2432bit );
56102 begin
56103 RotateProcs := AllRotators;
56104 _RotateBitmapRight( @Self );
56105 end;
56107 //[procedure _RotateBitmapLeft]
56108 procedure _RotateBitmapLeft( Src: PBitmap );
56109 begin
56110 _RotateBitmapRight( Src );
56111 _RotateBitmapRight( Src );
56112 _RotateBitmapRight( Src );
56113 end;
56115 //[procedure TBitmap.RotateLeft]
56116 procedure TBitmap.RotateLeft;
56117 begin
56118 RotateRight;
56119 _RotateBitmapRight( @Self );
56120 _RotateBitmapRight( @Self );
56121 end;
56123 //[procedure TBitmap.RotateLeftMono]
56124 procedure TBitmap.RotateLeftMono;
56125 begin
56126 if PixelFormat <> pf1bit then Exit;
56127 RotateProcs.proc_RotateBitmapMono := _RotateBitmapMono;
56128 _RotateBitmapRight( @Self );
56129 end;
56131 //[procedure TBitmap.RotateRightMono]
56132 procedure TBitmap.RotateRightMono;
56133 begin
56134 if PixelFormat <> pf1bit then Exit;
56135 RotateProcs.proc_RotateBitmapMono := _RotateBitmapMono;
56136 _RotateBitmapLeft( @Self );
56137 end;
56139 //[procedure TBitmap.RotateLeft16bit]
56140 procedure TBitmap.RotateLeft16bit;
56141 begin
56142 if PixelFormat <> pf16bit then Exit;
56143 RotateProcs.proc_RotateBitmap16bit := _RotateBitmap16bit;
56144 _RotateBitmapLeft( @Self );
56145 end;
56147 //[procedure TBitmap.RotateLeft4bit]
56148 procedure TBitmap.RotateLeft4bit;
56149 begin
56150 if PixelFormat <> pf4bit then Exit;
56151 RotateProcs.proc_RotateBitmap4bit := _RotateBitmap4bit;
56152 _RotateBitmapLeft( @Self );
56153 end;
56155 //[procedure TBitmap.RotateLeft8bit]
56156 procedure TBitmap.RotateLeft8bit;
56157 begin
56158 if PixelFormat <> pf8bit then Exit;
56159 RotateProcs.proc_RotateBitmap8bit := _RotateBitmap8bit;
56160 _RotateBitmapLeft( @Self );
56161 end;
56163 //[procedure TBitmap.RotateLeftTrueColor]
56164 procedure TBitmap.RotateLeftTrueColor;
56165 begin
56166 if not (PixelFormat in [ pf24bit, pf32bit ]) then Exit;
56167 RotateProcs.proc_RotateBitmap2432bit := _RotateBitmap2432bit;
56168 _RotateBitmapLeft( @Self );
56169 end;
56171 //[procedure TBitmap.RotateRight16bit]
56172 procedure TBitmap.RotateRight16bit;
56173 begin
56174 if PixelFormat <> pf16bit then Exit;
56175 RotateProcs.proc_RotateBitmap16bit := _RotateBitmap16bit;
56176 _RotateBitmapRight( @Self );
56177 end;
56179 //[procedure TBitmap.RotateRight4bit]
56180 procedure TBitmap.RotateRight4bit;
56181 begin
56182 if PixelFormat <> pf4bit then Exit;
56183 RotateProcs.proc_RotateBitmap4bit := _RotateBitmap4bit;
56184 _RotateBitmapRight( @Self );
56185 end;
56187 //[procedure TBitmap.RotateRight8bit]
56188 procedure TBitmap.RotateRight8bit;
56189 begin
56190 if PixelFormat <> pf8bit then Exit;
56191 RotateProcs.proc_RotateBitmap8bit := _RotateBitmap8bit;
56192 _RotateBitmapRight( @Self );
56193 end;
56195 //[procedure TBitmap.RotateRightTrueColor]
56196 procedure TBitmap.RotateRightTrueColor;
56197 begin
56198 if not (PixelFormat in [ pf24bit, pf32bit ]) then Exit;
56199 RotateProcs.proc_RotateBitmap2432bit := _RotateBitmap2432bit;
56200 _RotateBitmapRight( @Self );
56201 end;
56203 {$IFDEF ASM_VERSION}
56204 //[function TBitmap.GetPixels]
56205 function TBitmap.GetPixels(X, Y: Integer): TColor;
56207 PUSH EBX
56208 MOV EBX, EAX
56209 PUSH ECX
56210 PUSH EDX
56211 CALL GetEmpty
56212 PUSHFD
56213 OR EAX, -1
56214 POPFD
56215 JZ @@exit
56217 CALL StartDC
56218 PUSH dword ptr [ESP+12]
56219 PUSH dword ptr [ESP+12]
56220 PUSH EAX
56221 CALL Windows.GetPixel
56222 XCHG EBX, EAX
56223 CALL FinishDC
56224 XCHG EAX, EBX
56225 @@exit:
56226 POP EDX
56227 POP EDX
56228 POP EBX
56229 end;
56230 {$ELSE ASM_VERSION} //Pascal
56231 function TBitmap.GetPixels(X, Y: Integer): TColor;
56232 var DC: HDC;
56233 Save: THandle;
56234 begin
56235 Result := clNone;
56236 //if GetHandle = 0 then Exit;
56237 if Empty then Exit;
56238 fDetachCanvas( @Self );
56239 DC := CreateCompatibleDC( 0 );
56240 Save := SelectObject( DC, GetHandle );
56241 ASSERT( Save <> 0, 'Can not select bitmap to DC' );
56242 Result := Windows.GetPixel( DC, X, Y );
56243 SelectObject( DC, Save );
56244 DeleteDC( DC );
56245 end;
56246 {$ENDIF ASM_VERSION}
56248 {$IFDEF ASM_VERSION}
56249 //[procedure TBitmap.SetPixels]
56250 procedure TBitmap.SetPixels(X, Y: Integer; const Value: TColor);
56252 PUSH EBX
56253 MOV EBX, EAX
56254 PUSH ECX
56255 PUSH EDX
56256 CALL GetEmpty
56257 JZ @@exit
56259 CALL StartDC
56260 MOV EAX, Value
56261 CALL Color2RGB
56262 PUSH EAX
56263 PUSH dword ptr [ESP+16]
56264 PUSH dword ptr [ESP+16]
56265 PUSH dword ptr [ESP+16]
56266 CALL Windows.SetPixel
56267 CALL FinishDC
56268 @@exit:
56269 POP EDX
56270 POP ECX
56271 POP EBX
56272 end;
56273 {$ELSE ASM_VERSION} //Pascal
56274 procedure TBitmap.SetPixels(X, Y: Integer; const Value: TColor);
56275 var DC: HDC;
56276 Save: THandle;
56277 begin
56278 //if GetHandle = 0 then Exit;
56279 if Empty then Exit;
56280 fDetachCanvas( @Self );
56281 DC := CreateCompatibleDC( 0 );
56282 Save := SelectObject( DC, GetHandle );
56283 ASSERT( Save <> 0, 'Can not select bitmap to DC' );
56284 Windows.SetPixel( DC, X, Y, Color2RGB( Value ) );
56285 SelectObject( DC, Save );
56286 DeleteDC( DC );
56287 end;
56288 {$ENDIF ASM_VERSION}
56290 //[FUNCTION _GetDIBPixelsPalIdx]
56291 {$IFDEF ASM_VERSION}
56292 function _GetDIBPixelsPalIdx( Bmp: PBitmap; X, Y: Integer ): TColor;
56293 const szBIH = Sizeof(TBitmapInfoHeader);
56295 PUSH EBX
56296 PUSH EDI
56297 PUSH EDX
56298 XCHG EBX, EAX
56300 XCHG EAX, EDX
56301 MOV EDI, [EBX].TBitmap.fPixelsPerByteMask
56302 INC EDI
56304 DIV EDI
56305 DEC EDI
56306 XCHG ECX, EAX // EAX = Y, ECX = X div (Bmp.fPixeldPerByteMask+1)
56308 MOV EDX, [EBX].TBitmap.fScanLineDelta
56309 IMUL EDX
56311 ADD EAX, [EBX].TBitmap.fScanLine0
56312 MOVZX EAX, byte ptr[EAX+ECX]
56314 POP EDX
56315 MOV ECX, [EBX].TBitmap.fPixelsPerByteMask
56316 AND EDX, ECX
56317 SUB ECX, EDX
56319 PUSH EAX
56320 MOV EDI, [EBX].TBitmap.fDIBHeader
56321 MOVZX EAX, [EDI].TBitmapInfoHeader.biBitCount
56322 MUL ECX
56323 XCHG ECX, EAX
56324 POP EAX
56325 SHR EAX, CL
56326 AND EAX, [EBX].TBitmap.fPixelMask
56328 MOV EAX, [EDI+szBIH+EAX*4]
56329 CALL Color2RGBQuad
56331 POP EDI
56332 POP EBX
56333 end;
56334 {$ELSE ASM_VERSION} //Pascal
56335 function _GetDIBPixelsPalIdx( Bmp: PBitmap; X, Y: Integer ): TColor;
56336 var Pixel: Byte;
56337 begin
56338 Pixel := PByte( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta
56339 + (X div (Bmp.fPixelsPerByteMask + 1)) )^;
56340 Pixel := ( Pixel shr ( (Bmp.fPixelsPerByteMask - (X and Bmp.fPixelsPerByteMask))
56341 * Bmp.fDIBHeader.bmiHeader.biBitCount ) )
56342 and Bmp.fPixelMask;
56343 Result := TColor( Color2RGBQuad( TColor( PRGBQuad( DWORD(@Bmp.fDIBHeader.bmiColors[ 0 ])
56344 + Pixel * Sizeof( TRGBQuad ) )^ ) ) );
56345 end;
56346 {$ENDIF ASM_VERSION}
56347 //[END _GetDIBPixelsPalIdx]
56349 //[FUNCTION _GetDIBPixels16bit]
56350 {$IFDEF ASM_VERSION}
56351 function _GetDIBPixels16bit( Bmp: PBitmap; X, Y: Integer ): TColor;
56353 PUSH [EAX].TBitmap.fPixelMask
56354 PUSH EDX // X
56355 PUSH EAX
56356 MOV EAX, [EAX].TBitmap.fScanLineDelta
56357 IMUL ECX
56358 POP EDX
56359 ADD EAX, [EDX].TBitmap.fScanLine0
56360 POP ECX
56361 MOVZX EAX, word ptr [EAX+ECX*2]
56362 POP EDX
56363 CMP DL, 15
56364 JNE @@16bit
56366 MOV EDX, EAX
56367 SHR EDX, 7
56368 SHL EAX, 6
56369 MOV DH, AH
56370 AND DH, $F8
56371 SHL EAX, 13
56372 JMP @@1516bit
56374 @@16bit:
56375 MOV DL, AH
56376 SHL EAX, 5
56377 MOV DH, AH
56378 SHL EAX, 14
56379 @@1516bit:
56380 AND EAX, $F80000
56381 OR EAX, EDX
56382 AND AX, $FCF8
56383 end;
56384 {$ELSE ASM_VERSION} //Pascal
56385 function _GetDIBPixels16bit( Bmp: PBitmap; X, Y: Integer ): TColor;
56386 var Pixel: Word;
56387 begin
56388 Pixel := PWord( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta + X * 2 )^;
56389 if Bmp.fPixelMask = 15 then
56390 Result := (Pixel shr 7) and $F8 or (Pixel shl 6) and $F800
56391 or (Pixel shl 19) and $F80000
56392 else
56393 Result := (Pixel shr 8) and $F8 or (Pixel shl 5) and $FC00
56394 or (Pixel shl 19) and $F80000;
56395 end;
56396 {$ENDIF ASM_VERSION}
56397 //[END _GetDIBPixels16bit]
56399 //[FUNCTION _GetDIBPixelsTrueColor]
56400 {$IFDEF ASM_VERSION}
56401 function _GetDIBPixelsTrueColor( Bmp: PBitmap; X, Y: Integer ): TColor;
56403 PUSH EBX
56404 XCHG EBX, EAX
56405 PUSH EDX
56406 MOV EAX, [EBX].TBitmap.fScanLineDelta
56407 IMUL ECX
56408 XCHG ECX, EAX
56409 POP EDX
56410 MOV EAX, [EBX].TBitmap.fBytesPerPixel
56411 MUL EDX
56412 ADD EAX, [EBX].TBitmap.fScanLine0
56413 MOV EAX, [EAX+ECX]
56414 AND EAX, $FFFFFF
56415 CALL Color2RGBQuad
56416 POP EBX
56417 end;
56418 {$ELSE ASM_VERSION} //Pascal
56419 function _GetDIBPixelsTrueColor( Bmp: PBitmap; X, Y: Integer ): TColor;
56420 var Pixel: DWORD;
56421 begin
56422 Pixel := PDWORD( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta +
56423 X * Bmp.fBytesPerPixel )^ and $FFFFFF;
56424 Result := TColor( Color2RGBQuad( TColor( Pixel ) ) );
56425 end;
56426 {$ENDIF ASM_VERSION}
56427 //[END _GetDIBPixelsTrueColor]
56429 {$IFDEF ASM_VERSION}
56430 //[function TBitmap.GetDIBPixels]
56431 function TBitmap.GetDIBPixels(X, Y: Integer): TColor;
56433 CMP word ptr [EAX].fGetDIBPixels+2, 0
56434 JNZ @@assigned
56436 // if not assigned, this preparing will be performed for first call:
56437 CMP [EAX].fHandleType, bmDDB
56438 JZ @@GetPixels
56440 PUSHAD
56441 MOV EBX, EAX
56442 XOR EDX, EDX
56443 CALL GetScanLine
56444 MOV [EBX].fScanLine0, EAX
56445 XOR EDX, EDX
56446 INC EDX
56447 MOV EAX, EBX
56448 CALL GetScanLine
56449 SUB EAX, [EBX].fScanLine0
56450 MOV [EBX].fScanLineDelta, EAX
56451 MOV EAX, EBX
56452 CALL GetPixelFormat
56453 MOVZX ECX, AL
56454 MOV DX, $0F00
56455 MOV byte ptr [EBX].fBytesPerPixel, 4
56456 XOR EAX, EAX
56457 LOOP @@if4bit
56458 MOV DX, $0107
56459 JMP @@1bit4bit8bit
56460 @@if4bit:
56461 LOOP @@if8bit
56462 INC EDX // MOV DX, $0F01
56463 JMP @@1bit4bit8bit
56464 @@if8bit:
56465 LOOP @@if15bit
56466 MOV DH, $FF //MOV DX, $FF00
56467 @@1bit4bit8bit:
56468 MOV EAX, offset[_GetDIBPixelsPalIdx]
56469 @@if15bit:
56470 LOOP @@if16bit
56471 //MOV DH, $0F
56472 DEC DH
56473 INC ECX
56474 @@if16bit:
56475 LOOP @@if24bit
56476 INC DH
56477 MOV EAX, offset[_GetDIBPixels16bit]
56478 @@if24bit:
56479 LOOP @@if32bit
56480 DEC [EBX].fBytesPerPixel
56481 INC ECX
56482 DEC EDX
56483 @@if32bit:
56484 LOOP @@iffin
56485 INC EDX
56486 MOV EAX, offset[_GetDIBPixelsTrueColor]
56487 @@iffin:
56488 MOV byte ptr [EBX].fPixelMask, DH
56489 MOV byte ptr [EBX].fPixelsPerByteMask, DL
56490 MOV [EBX].fGetDIBPixels, EAX
56491 TEST EAX, EAX
56492 POPAD
56493 @@GetPixels:
56494 JZ GetPixels
56496 @@assigned:
56497 JMP [EAX].fGetDIBPixels
56498 end;
56499 {$ELSE ASM_VERSION} //Pascal
56500 function TBitmap.GetDIBPixels(X, Y: Integer): TColor;
56501 begin
56502 if not Assigned( fGetDIBPixels ) then
56503 begin
56504 if fHandleType = bmDIB then
56505 begin
56506 fScanLine0 := ScanLine[ 0 ];
56507 fScanLineDelta := Integer(ScanLine[ 1 ]) - Integer(fScanLine0);
56508 case PixelFormat of
56509 pf1bit:
56510 begin
56511 fPixelMask := $01;
56512 fPixelsPerByteMask := 7;
56513 fGetDIBPixels := _GetDIBPixelsPalIdx;
56514 end;
56515 pf4bit:
56516 begin
56517 fPixelMask := $0F;
56518 fPixelsPerByteMask := 1;
56519 fGetDIBPixels := _GetDIBPixelsPalIdx;
56520 end;
56521 pf8bit:
56522 begin
56523 fPixelMask := $FF;
56524 fPixelsPerByteMask := 0;
56525 fGetDIBPixels := _GetDIBPixelsPalIdx;
56526 end;
56527 pf15bit:
56528 begin
56529 fPixelMask := 15;
56530 fGetDIBPixels := _GetDIBPixels16bit;
56531 end;
56532 pf16bit:
56533 begin
56534 fPixelMask := 16;
56535 fGetDIBPixels := _GetDIBPixels16bit;
56536 end;
56537 pf24bit:
56538 begin
56539 fPixelsPerByteMask := 0;
56540 fBytesPerPixel := 3;
56541 fGetDIBPixels := _GetDIBPixelsTrueColor;
56542 end;
56543 pf32bit:
56544 begin
56545 fPixelsPerByteMask := 1;
56546 fBytesPerPixel := 4;
56547 fGetDIBPixels := _GetDIBPixelsTrueColor;
56548 end;
56549 else;
56550 end;
56551 end;
56552 if not Assigned( fGetDIBPixels ) then
56553 begin
56554 Result := Pixels[ X, Y ];
56555 Exit;
56556 end;
56557 end;
56558 Result := fGetDIBPixels( @Self, X, Y );
56559 end;
56560 {$ENDIF ASM_VERSION}
56562 //[PROCEDURE _SetDIBPixels1bit]
56563 {$IFDEF ASM_VERSION}
56564 procedure _SetDIBPixels1bit( Bmp: PBitmap; X, Y: Integer; Value: TColor );
56566 PUSH EDX
56567 PUSH [EAX].TBitmap.fScanLine0
56568 PUSH ECX
56569 PUSH [EAX].TBitmap.fScanLineDelta
56570 MOV EAX, Value
56571 CALL Color2RGB
56572 MOV EDX, EAX
56573 SHR EAX, 16
56574 ADD AL, DL
56575 ADC AL, DH
56576 CMP EAX, 170
56577 SETGE CL
56578 AND ECX, 1
56579 SHL ECX, 7
56580 POP EAX
56581 POP EDX
56582 IMUL EDX
56583 POP EDX
56584 ADD EAX, EDX
56585 POP EDX
56586 PUSH ECX
56587 MOV ECX, EDX
56588 SHR EDX, 3
56589 ADD EAX, EDX
56590 AND ECX, 7
56591 MOV DX, $FF7F
56592 SHR EDX, CL
56593 AND byte ptr [EAX], DL
56594 POP EDX
56595 SHR EDX, CL
56596 OR byte ptr [EAX], DL
56597 end;
56598 {$ELSE ASM_VERSION} //Pascal
56599 procedure _SetDIBPixels1bit( Bmp: PBitmap; X, Y: Integer; Value: TColor );
56600 var Pixel: Byte;
56601 Pos: PByte;
56602 Shf: Integer;
56603 begin
56604 Value := Color2RGB( Value );
56605 if ((Value shr 16) and $FF) + ((Value shr 8) and $FF) + (Value and $FF)
56606 < 255 * 3 div 2 then Pixel := 0 else Pixel := $80;
56607 Pos := PByte( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta + X div 8 );
56608 Shf := X and 7;
56609 Pos^ := Pos^ and ($FF7F shr Shf) or (Pixel shr Shf);
56610 end;
56611 {$ENDIF ASM_VERSION}
56612 //[END _SetDIBPixels1bit]
56614 //[PROCEDURE _SetDIBPixelsPalIdx]
56615 {$IFDEF ASM_VERSION}
56616 procedure _SetDIBPixelsPalIdx( Bmp: PBitmap; X, Y: Integer; Value: TColor );
56618 XCHG EAX, EBP
56619 PUSH EDX // -> X
56620 PUSH ECX // -> Y
56621 MOV ECX, [EBP].TBitmap.fPixelsPerByteMask
56622 INC ECX
56623 XCHG EAX, EDX
56625 DIV ECX
56626 XCHG ECX, EAX // ECX = X div (fPixelsPerByteMask+1)
56627 POP EAX // <- Y
56628 MOV EDX, [EBP].TBitmap.fScanLineDelta
56629 IMUL EDX
56630 ADD ECX, EAX
56631 ADD ECX, [EBP].TBitmap.fScanLine0 // ECX = Pos
56632 PUSH ECX // -> Pos
56634 MOV EDX, [ESP+16] // Value
56635 MOV EAX, EBP
56636 CALL TBitmap.DIBPalNearestEntry // EAX = Pixel
56638 POP ECX // <- Pos
56639 POP EDX // <- X
56641 PUSH EAX // -> Pixel
56643 MOV EAX, [EBP].TBitmap.fPixelsPerByteMask
56644 AND EDX, EAX
56645 SUB EAX, EDX
56646 MOV EDX, [EBP].TBitmap.fDIBHeader
56647 MOVZX EDX, [EDX].TBitmapInfoHeader.biBitCount
56648 MUL EDX // EAX = Shf
56650 XCHG ECX, EAX // ECX = Shf, EAX = Pos
56651 MOV EDX, [EBP].TBitmap.fPixelMask
56652 SHL EDX, CL
56653 NOT EDX
56654 AND byte ptr [EAX], DL
56656 POP EDX // <- Pixel
56657 SHL EDX, CL
56658 OR byte ptr [EAX], DL
56659 end;
56660 {$ELSE ASM_VERSION} //Pascal
56661 procedure _SetDIBPixelsPalIdx( Bmp: PBitmap; X, Y: Integer; Value: TColor );
56662 var Pixel: Byte;
56663 Pos: PByte;
56664 Shf: Integer;
56665 begin
56666 Pixel := Bmp.DIBPalNearestEntry( Value );
56667 Pos := PByte( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta
56668 + X div (Bmp.fPixelsPerByteMask + 1) );
56669 Shf := (Bmp.fPixelsPerByteMask - (X and Bmp.fPixelsPerByteMask))
56670 * Bmp.fDIBHeader.bmiHeader.biBitCount;
56671 Pos^ := Pos^ and not (Bmp.fPixelMask shl Shf) or (Pixel shl Shf);
56672 end;
56673 {$ENDIF ASM_VERSION}
56674 //[END _SetDIBPixelsPalIdx]
56676 //[PROCEDURE _SetDIBPixels16bit]
56677 {$IFDEF ASM_VERSION}
56678 procedure _SetDIBPixels16bit( Bmp: PBitmap; X, Y: Integer; Value: TColor );
56680 ADD EDX, EDX
56681 ADD EDX, [EAX].TBitmap.fScanLine0
56682 PUSH EDX // -> X*2 + Bmp.fScanLine0
56683 PUSH [EAX].TBitmap.fPixelMask
56684 MOV EAX, [EAX].TBitmap.fScanLineDelta
56685 IMUL ECX
56686 PUSH EAX // -> Y* Bmp.fScanLineDelta
56687 MOV EAX, Value
56688 CALL Color2RGB
56689 POP EBP // <- Y* Bmp.fScanLineDelta
56690 POP EDX
56691 XOR ECX, ECX
56692 SUB DL, 16
56693 JZ @@16bit
56695 MOV CH, AL
56696 SHR CH, 1
56697 SHR EAX, 6
56698 MOV EDX, EAX
56699 AND DX, $3E0
56700 SHR EAX, 13
56701 JMP @@1516
56703 @@16bit:
56704 {$IFDEF PARANOIA}
56705 DB $24, $F8
56706 {$ELSE}
56707 AND AL, $F8
56708 {$ENDIF}
56709 MOV CH, AL
56710 SHR EAX, 5
56711 MOV EDX, EAX
56712 AND DX, $7E0
56713 SHR EAX, 14
56715 @@1516:
56716 MOV AH, CH
56717 AND AX, $FC1F
56718 OR AX, DX
56720 POP EDX
56721 MOV [EBP+EDX], AX
56722 end;
56723 {$ELSE ASM_VERSION} //Pascal
56724 procedure _SetDIBPixels16bit( Bmp: PBitmap; X, Y: Integer; Value: TColor );
56725 var RGB16: Word;
56726 Pos: PWord;
56727 begin
56728 Value := Color2RGB( Value );
56729 if Bmp.fPixelMask = 15 then
56730 RGB16 := (Value shr 19) and $001F or (Value shr 6) and $03E0
56731 or (Value shl 7) and $7C00
56732 else
56733 RGB16 := (Value shr 19) and $001F or (Value shr 5) and $07E0
56734 or (Value shl 8) and $F800;
56735 Pos := PWord( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta + X * 2 );
56736 Pos^ := RGB16;
56737 end;
56738 {$ENDIF ASM_VERSION}
56739 //[END _SetDIBPixels16bit]
56741 //[PROCEDURE _SetDIBPixelsTrueColor]
56742 {$IFDEF ASM_VERSION}
56743 procedure _SetDIBPixelsTrueColor( Bmp: PBitmap; X, Y: Integer; Value: TColor );
56745 PUSH [EAX].TBitmap.fScanLineDelta
56746 PUSH [EAX].TBitmap.fScanLine0
56747 MOV EAX, [EAX].TBitmap.fBytesPerPixel
56748 MUL EDX
56749 POP EDX
56750 ADD EDX, EAX
56751 POP EAX
56752 PUSH EDX
56753 IMUL ECX
56754 POP EDX
56755 ADD EDX, EAX
56756 PUSH EDX
56757 MOV EAX, Value
56758 CALL Color2RGBQuad
56759 POP EDX
56760 AND dword ptr [EDX], $FF000000
56761 OR [EDX], EAX
56762 end;
56763 {$ELSE ASM_VERSION} //Pascal
56764 procedure _SetDIBPixelsTrueColor( Bmp: PBitmap; X, Y: Integer; Value: TColor );
56765 var RGB: TRGBQuad;
56766 Pos: PDWord;
56767 begin
56768 //Value := Color2RGB( Value );
56769 RGB := Color2RGBQuad( Value );
56770 Pos := PDWORD( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta
56771 + X * Bmp.fBytesPerPixel );
56772 Pos^ := Pos^ and $FF000000 or DWORD(RGB);
56773 end;
56774 {$ENDIF ASM_VERSION}
56775 //[END _SetDIBPixelsTrueColor]
56777 {$IFDEF ASM_VERSION}
56778 //[procedure TBitmap.SetDIBPixels]
56779 procedure TBitmap.SetDIBPixels(X, Y: Integer; const Value: TColor);
56781 CMP word ptr [EAX].fSetDIBPixels+2, 0
56782 JNZ @@assigned
56783 PUSHAD
56784 MOV EBX, EAX
56785 XOR EDX, EDX
56786 CMP [EBX].fHandleType, DL // bmDIB = 0
56787 JNE @@ddb
56788 CALL GetScanLine
56789 MOV [EBX].fScanLine0, EAX
56790 XOR EDX, EDX
56791 INC EDX
56792 MOV EAX, EBX
56793 CALL GetScanLine
56794 SUB EAX, [EBX].fScanLine0
56795 MOV [EBX].fScanLineDelta, EAX
56796 MOV EAX, EBX
56797 CALL GetPixelFormat
56798 MOVZX ECX, AL
56799 MOV DX, $0F01
56800 MOV EAX, offset[_SetDIBPixelsPalIdx]
56801 MOV byte ptr [EBX].fBytesPerPixel, 4
56802 LOOP @@if4bit
56803 MOV EAX, offset[_SetDIBPixels1bit]
56804 @@if4bit:
56805 LOOP @@if8bit
56806 @@if8bit:
56807 LOOP @@if15bit
56808 DEC DL
56809 MOV DH, $FF
56810 @@if15bit:
56811 LOOP @@if16bit
56812 DEC DH
56813 INC ECX
56814 @@if16bit:
56815 LOOP @@if24bit
56816 INC DH
56817 MOV EAX, offset[_SetDIBPixels16bit]
56818 @@if24bit:
56819 LOOP @@if32bit
56820 DEC EDX
56821 DEC [EBX].fBytesPerPixel
56822 INC ECX
56823 @@if32bit:
56824 LOOP @@ifend
56825 INC EDX
56826 MOV EAX, offset[_SetDIBPixelsTrueColor]
56827 @@ifend:
56828 MOV byte ptr [EBX].fPixelMask, DH
56829 MOV byte ptr [EBX].fPixelsPerByteMask, DL
56830 MOV [EBX].fSetDIBPixels, EAX
56831 TEST EAX, EAX
56832 @@ddb:
56833 POPAD
56834 JNZ @@assigned
56835 PUSH Value
56836 CALL SetPixels
56837 JMP @@exit
56838 @@assigned:
56839 PUSH Value
56840 CALL [EAX].fSetDIBPixels
56841 @@exit:
56842 end;
56843 {$ELSE ASM_VERSION} //Pascal
56844 procedure TBitmap.SetDIBPixels(X, Y: Integer; const Value: TColor);
56845 begin
56846 if not Assigned( fSetDIBPixels ) then
56847 begin
56848 if fHandleType = bmDIB then
56849 begin
56850 fScanLine0 := ScanLine[ 0 ];
56851 fScanLineDelta := Integer(ScanLine[ 1 ]) - Integer(fScanLine0);
56852 case PixelFormat of
56853 pf1bit:
56854 begin
56855 //fPixelMask := $01;
56856 //fPixelsPerByteMask := 7;
56857 fSetDIBPixels := _SetDIBPixels1bit;
56858 end;
56859 pf4bit:
56860 begin
56861 fPixelMask := $0F;
56862 fPixelsPerByteMask := 1;
56863 fSetDIBPixels := _SetDIBPixelsPalIdx;
56864 end;
56865 pf8bit:
56866 begin
56867 fPixelMask := $FF;
56868 fPixelsPerByteMask := 0;
56869 fSetDIBPixels := _SetDIBPixelsPalIdx;
56870 end;
56871 pf15bit:
56872 begin
56873 fPixelMask := 15;
56874 fSetDIBPixels := _SetDIBPixels16bit;
56875 end;
56876 pf16bit:
56877 begin
56878 fPixelMask := 16;
56879 fSetDIBPixels := _SetDIBPixels16bit;
56880 end;
56881 pf24bit:
56882 begin
56883 fPixelsPerByteMask := 0;
56884 fBytesPerPixel := 3;
56885 fSetDIBPixels := _SetDIBPixelsTrueColor;
56886 end;
56887 pf32bit:
56888 begin
56889 fPixelsPerByteMask := 1;
56890 fBytesPerPixel := 4;
56891 fSetDIBPixels := _SetDIBPixelsTrueColor;
56892 end;
56893 else;
56894 end;
56895 end;
56896 if not Assigned( fSetDIBPixels ) then
56897 begin
56898 Pixels[ X, Y ] := Value;
56899 Exit;
56900 end;
56901 end;
56902 fSetDIBPixels( @Self, X, Y, Value );
56903 end;
56904 {$ENDIF ASM_VERSION}
56906 {$IFDEF ASM_VERSION}
56907 //[procedure TBitmap.FlipVertical]
56908 procedure TBitmap.FlipVertical;
56910 PUSH EBX
56911 MOV EBX, EAX
56912 MOV ECX, [EBX].fHandle
56913 JECXZ @@noHandle
56915 CALL StartDC
56916 PUSH SrcCopy
56917 MOV EDX, [EBX].fHeight
56918 PUSH EDX
56919 MOV ECX, [EBX].fWidth
56920 PUSH ECX
56921 PUSH 0
56922 PUSH 0
56923 PUSH EAX
56924 NEG EDX
56925 PUSH EDX
56926 PUSH ECX
56927 NEG EDX
56928 DEC EDX
56929 PUSH EDX
56930 PUSH 0
56931 PUSH EAX
56932 CALL StretchBlt
56933 CALL FinishDC
56934 POP EBX
56937 @@noHandle:
56938 MOV ECX, [EBX].fDIBBits
56939 JECXZ @@exit
56941 PUSHAD //----------------------------------------\
56942 XOR EBP, EBP // Y = 0
56943 //+++++++++++++++++++++++++++ provide fScanLineSize
56944 MOV EAX, EBX
56945 MOV EDX, EBP
56946 CALL GetScanLine //
56947 SUB ESP, [EBX].fScanLineSize
56949 @@loo: LEA EAX, [EBP*2]
56950 CMP EAX, [EBX].fHeight
56951 JG @@finloo
56953 MOV EAX, EBX
56954 MOV EDX, EBP
56955 CALL GetScanLine
56956 MOV ESI, EAX // ESI = ScanLine[ Y ]
56957 MOV EDX, ESP
56958 MOV ECX, [EBX].fScanLineSize
56959 PUSH ECX
56960 CALL System.Move
56962 MOV EAX, EBX
56963 MOV EDX, [EBX].fHeight
56964 SUB EDX, EBP
56965 DEC EDX
56966 CALL GetScanLine
56967 MOV EDI, EAX
56968 MOV EDX, ESI
56969 POP ECX
56970 PUSH ECX
56971 CALL System.Move
56973 POP ECX
56974 MOV EAX, ESP
56975 MOV EDX, EDI
56976 CALL System.Move
56978 INC EBP
56979 JMP @@loo
56981 @@finloo:
56982 ADD ESP, [EBX].fScanLineSize
56983 POPAD
56984 @@exit:
56985 POP EBX
56986 end;
56987 {$ELSE ASM_VERSION} //Pascal
56988 procedure TBitmap.FlipVertical;
56989 var DC: HDC;
56990 Save: THandle;
56991 TmpScan: PByte;
56992 Y: Integer;
56993 begin
56994 if fHandle <> 0 then
56995 begin
56996 fDetachCanvas( @Self );
56997 DC := CreateCompatibleDC( 0 );
56998 Save := SelectObject( DC, fHandle );
56999 StretchBlt( DC, 0, fHeight - 1, fWidth, -fHeight, DC, 0, 0, fWidth, fHeight, SRCCOPY );
57000 SelectObject( DC, Save );
57001 DeleteDC( DC );
57003 else
57004 if fDIBBits <> nil then
57005 begin
57006 GetMem( TmpScan, ScanLineSize );
57007 for Y := 0 to fHeight div 2 do
57008 begin
57009 Move( ScanLine[ Y ]^, TmpScan^, fScanLineSize );
57010 Move( ScanLine[ fHeight - Y - 1 ]^, ScanLine[ Y ]^, fScanLineSize );
57011 Move( TmpScan^, ScanLine[ fHeight - Y - 1 ]^, fScanLineSize );
57012 end;
57013 end;
57014 end;
57015 {$ENDIF ASM_VERSION}
57017 {$IFDEF ASM_VERSION}
57018 //[procedure TBitmap.FlipHorizontal]
57019 procedure TBitmap.FlipHorizontal;
57021 PUSH EBX
57022 MOV EBX, EAX
57023 CALL GetHandle
57024 TEST EAX, EAX
57025 JZ @@exit
57027 CALL StartDC
57028 PUSH SrcCopy
57029 MOV EDX, [EBX].fHeight
57030 PUSH EDX
57031 MOV ECX, [EBX].fWidth
57032 PUSH ECX
57033 PUSH 0
57034 PUSH 0
57035 PUSH EAX
57036 PUSH EDX
57037 NEG ECX
57038 PUSH ECX
57039 PUSH 0
57040 NEG ECX
57041 DEC ECX
57042 PUSH ECX
57043 PUSH EAX
57044 CALL StretchBlt
57045 CALL FinishDC
57046 @@exit:
57047 POP EBX
57048 end;
57049 {$ELSE ASM_VERSION} //Pascal
57050 procedure TBitmap.FlipHorizontal;
57051 var DC: HDC;
57052 Save: THandle;
57053 begin
57054 if GetHandle <> 0 then
57055 begin
57056 fDetachCanvas( @Self );
57057 DC := CreateCompatibleDC( 0 );
57058 Save := SelectObject( DC, fHandle );
57059 StretchBlt( DC, fWidth - 1, 0, -fWidth, fHeight, DC, 0, 0, fWidth, fHeight, SRCCOPY );
57060 SelectObject( DC, Save );
57061 DeleteDC( DC );
57062 end;
57063 end;
57064 {$ENDIF ASM_VERSION}
57066 {$IFDEF ASM_VERSION}
57067 //[procedure TBitmap.CopyRect]
57068 procedure TBitmap.CopyRect(const DstRect: TRect; SrcBmp: PBitmap;
57069 const SrcRect: TRect);
57071 PUSHAD
57072 MOV EBX, EAX
57073 MOV ESI, ECX
57074 MOV EDI, EDX
57075 CALL GetHandle
57076 TEST EAX, EAX
57077 JZ @@exit
57078 MOV EAX, ESI
57079 CALL GetHandle
57080 TEST EAX, EAX
57081 JZ @@exit
57082 CALL StartDC
57083 XCHG EBX, ESI
57084 CMP EBX, ESI
57085 JNZ @@diff1
57086 PUSH EAX
57087 PUSH 0
57088 JMP @@nodiff1
57089 @@diff1:
57090 CALL StartDC
57091 @@nodiff1:
57092 PUSH SrcCopy // ->
57093 MOV EBP, [SrcRect]
57094 MOV EAX, [EBP].TRect.Bottom
57095 MOV EDX, [EBP].TRect.Top
57096 SUB EAX, EDX
57097 PUSH EAX // ->
57098 MOV EAX, [EBP].TRect.Right
57099 MOV ECX, [EBP].TRect.Left
57100 SUB EAX, ECX
57101 PUSH EAX // ->
57102 PUSH EDX // ->
57103 PUSH ECX // ->
57104 PUSH dword ptr [ESP+24] // -> DCsrc
57105 MOV EAX, [EDI].TRect.Bottom
57106 MOV EDX, [EDI].TRect.Top
57107 SUB EAX, EDX
57108 PUSH EAX // ->
57109 MOV EAX, [EDI].TRect.Right
57110 MOV ECX, [EDI].TRect.Left
57111 SUB EAX, ECX
57112 PUSH EAX // ->
57113 PUSH EDX // ->
57114 PUSH ECX // ->
57115 PUSH dword ptr [ESP+13*4] // -> DCdst
57116 CALL StretchBlt
57117 CMP EBX, ESI
57118 JNE @@diff2
57119 POP ECX
57120 POP ECX
57121 JMP @@nodiff2
57122 @@diff2:
57123 CALL FinishDC
57124 @@nodiff2:
57125 CALL FinishDC
57126 @@exit:
57127 POPAD
57128 end;
57129 {$ELSE ASM_VERSION} //Pascal
57130 procedure TBitmap.CopyRect(const DstRect: TRect; SrcBmp: PBitmap;
57131 const SrcRect: TRect);
57132 var DCsrc, DCdst: HDC;
57133 SaveSrc, SaveDst: THandle;
57134 begin
57135 if (GetHandle = 0) or (SrcBmp.GetHandle = 0) then Exit;
57136 fDetachCanvas( @Self );
57137 fDetachCanvas( SrcBmp );
57138 DCsrc := CreateCompatibleDC( 0 );
57139 SaveSrc := SelectObject( DCsrc, SrcBmp.fHandle );
57140 DCdst := DCsrc;
57141 SaveDst := 0;
57142 if SrcBmp <> @Self then
57143 begin
57144 DCdst := CreateCompatibleDC( 0 );
57145 SaveDst := SelectObject( DCdst, fHandle );
57146 end;
57147 StretchBlt( DCdst, DstRect.Left, DstRect.Top, DstRect.Right - DstRect.Left,
57148 DstRect.Bottom - DstRect.Top, DCsrc, SrcRect.Left, SrcRect.Top,
57149 SrcRect.Right - SrcRect.Left, SrcRect.Bottom - SrcRect.Top,
57150 SRCCOPY );
57151 if SrcBmp <> @Self then
57152 begin
57153 SelectObject( DCdst, SaveDst );
57154 DeleteDC( DCdst );
57155 end;
57156 SelectObject( DCsrc, SaveSrc );
57157 DeleteDC( DCsrc );
57158 end;
57159 {$ENDIF ASM_VERSION}
57162 //[function TBitmap.CopyToClipboard]
57163 function TBitmap.CopyToClipboard: Boolean;
57164 var DibMem: PChar;
57165 HdrSize: Integer;
57166 Gbl: HGlobal;
57167 begin
57168 Result := FALSE;
57169 if Applet = nil then Exit;
57170 if not OpenClipboard( Applet.GetWindowHandle ) then
57171 Exit;
57172 if EmptyClipboard then
57173 begin
57174 HandleType := bmDIB;
57175 HdrSize := sizeof( TBitmapInfoHeader );
57176 if fDIBHeader.bmiHeader.biBitCount <= 8 then
57177 Inc( HdrSize,
57178 (1 shl fDIBHeader.bmiHeader.biBitCount) * Sizeof( TRGBQuad ) );
57179 Gbl := GlobalAlloc( GMEM_MOVEABLE, HdrSize + fDIBSize );
57180 DibMem := GlobalLock( Gbl );
57181 if DibMem <> nil then
57182 begin
57183 Move( fDIBHeader^, DibMem^, HdrSize );
57184 Move( fDIBBits^, Pointer( Integer( DibMem ) + HdrSize )^, fDIBSize );
57185 if not GlobalUnlock( Gbl ) and (GetLastError = NO_ERROR) then
57186 begin
57187 Result := SetClipboardData( CF_DIB, Gbl ) <> 0;
57188 end;
57189 end;
57190 end;
57191 CloseClipboard;
57192 end;
57194 //[function TBitmap.PasteFromClipboard]
57195 function TBitmap.PasteFromClipboard: Boolean;
57196 var Gbl: HGlobal;
57197 //DIBPtr: PChar;
57198 Size {, HdrSize}: Integer;
57199 Mem: PChar;
57200 Strm: PStream;
57201 begin
57202 Result := FALSE;
57203 if Applet = nil then Exit;
57204 if not OpenClipboard( Applet.GetWindowHandle ) then Exit;
57206 if IsClipboardFormatAvailable( CF_DIB ) then
57207 begin
57208 Gbl := GetClipboardData( CF_DIB );
57209 if Gbl <> 0 then
57210 begin
57211 Size := GlobalSize( Gbl );
57212 Mem := GlobalLock( Gbl );
57214 if (Size > 0) and (Mem <> nil) then
57215 begin
57216 Strm := NewMemoryStream;
57217 Strm.Write( Mem^, Size );
57218 Strm.Position := 0;
57219 LoadFromStreamEx( Strm );
57220 Strm.Free;
57221 Result := not Empty;
57222 end;
57223 FINALLY
57224 GlobalUnlock( Gbl );
57225 END;
57226 end;
57227 end;
57228 FINALLY
57229 CloseClipboard;
57230 END;
57231 end;
57241 ///////////////////////////////////////////////////////////////////////
57244 // I C O N
57247 ///////////////////////////////////////////////////////////////////////
57249 { -- icon -- }
57251 //[function NewIcon]
57252 function NewIcon: PIcon;
57253 begin
57255 New( Result, Create );
57256 {+}{++}(*Result := TIcon.Create;*){--}
57257 Result.FSize := 32;
57258 end;
57260 { TIcon }
57262 //[PROCEDURE asmIconEmpty]
57263 {$IFDEF ASM_VERSION}
57264 procedure asmIconEmpty( Icon: PIcon );
57266 CMP [EAX].TIcon.fHandle, 0
57267 end;
57268 {$ENDIF ASM_VERSION}
57269 //[END asmIconEmpty]
57271 {$IFDEF ASM_VERSION}
57272 //[procedure TIcon.Clear]
57273 procedure TIcon.Clear;
57274 asm //cmd //opd
57275 XOR ECX, ECX
57276 XCHG ECX, [EAX].fHandle
57277 JECXZ @@1
57278 CMP [EAX].fShareIcon, 0
57279 JNZ @@1
57280 PUSH EAX
57281 PUSH ECX
57282 CALL DestroyIcon
57283 POP EAX
57284 @@1: MOV [EAX].fShareIcon, 0
57285 end;
57286 {$ELSE ASM_VERSION} //Pascal
57287 procedure TIcon.Clear;
57288 begin
57289 if fHandle <> 0 then
57290 begin
57291 if not FShareIcon then
57292 //DeleteObject( fHandle );
57293 DestroyIcon( fHandle );
57294 fHandle := 0;
57295 end;
57296 fShareIcon := False;
57297 end;
57298 {$ENDIF ASM_VERSION}
57300 {$IFDEF ASM_VERSION}
57301 //[function TIcon.Convert2Bitmap]
57302 function TIcon.Convert2Bitmap(TranColor: TColor): HBitmap;
57303 asm //cmd //opd
57304 PUSH EBX
57305 PUSH ESI
57306 PUSH EDI
57307 PUSH EBP
57308 MOV EBX, EAX
57309 MOV EBP, EDX
57310 XOR EDX, EDX
57311 CALL asmIconEmpty
57312 JZ @@ret_0
57313 PUSH 0
57314 CALL GetDC
57315 PUSH EAX //> DC0
57316 PUSH EAX
57317 CALL CreateCompatibleDC
57318 XCHG EDI, EAX
57319 MOV EDX, [EBX].fSize
57321 POP EAX
57322 PUSH EAX
57323 PUSH EDX //>Bottom
57324 PUSH EDX //>Right
57325 PUSH 0 //>Top
57326 PUSH 0 //>Left
57328 PUSH EDX
57329 PUSH EDX
57330 PUSH EAX
57331 CALL CreateCompatibleBitmap
57332 XCHG EBP, EAX
57334 CALL Color2RGB
57335 PUSH EAX
57337 PUSH EBP
57338 PUSH EDI
57339 CALL SelectObject
57340 XCHG ESI, EAX
57342 CALL CreateSolidBrush
57344 MOV EDX, ESP
57345 PUSH EAX
57346 PUSH EAX
57347 PUSH EDX
57348 PUSH EDI
57349 CALL Windows.FillRect
57350 CALL DeleteObject
57352 XCHG EAX, EBX
57353 MOV EDX, EDI
57354 XOR ECX, ECX
57355 PUSH ECX
57356 CALL Draw
57358 PUSH EDI
57359 PUSH ESI
57360 CALL FinishDC
57362 ADD ESP, 16
57363 PUSH 0
57364 CALL ReleaseDC
57365 MOV EDX, EBP
57367 @@ret_0:
57368 XCHG EAX, EDX
57369 POP EBP
57370 POP EDI
57371 POP ESI
57372 POP EBX
57373 end;
57374 {$ELSE ASM_VERSION} //Pascal
57375 function TIcon.Convert2Bitmap(TranColor: TColor): HBitmap;
57376 var DC0, DC2: HDC;
57377 Save: THandle;
57378 Br: HBrush;
57379 begin
57380 Result := 0;
57381 if Empty then Exit;
57382 DC0 := GetDC( 0 );
57383 DC2 := CreateCompatibleDC( DC0 );
57384 Result := CreateCompatibleBitmap( DC0, fSize, fSize );
57385 Save := SelectObject( DC2, Result );
57386 Br := CreateSolidBrush( Color2RGB( TranColor ) );
57387 FillRect( DC2, MakeRect( 0, 0, fSize, fSize ), Br );
57388 DeleteObject( Br );
57389 Draw( DC2, 0, 0 );
57390 SelectObject( DC2, Save );
57391 DeleteDC( DC2 );
57392 ReleaseDC( 0, DC0 );
57393 end;
57394 {$ENDIF ASM_VERSION}
57396 {$IFDEF ASM_VERSION}
57397 //[destructor TIcon.Destroy]
57398 destructor TIcon.Destroy;
57399 asm //cmd //opd
57400 PUSH EAX
57401 CALL Clear
57402 POP EAX
57403 CALL TObj.Destroy
57404 end;
57405 {$ELSE ASM_VERSION} //Pascal
57406 destructor TIcon.Destroy;
57407 begin
57408 Clear;
57409 inherited;
57410 end;
57411 {$ENDIF ASM_VERSION}
57413 {$IFDEF ASM_VERSION}
57414 //[procedure TIcon.Draw]
57415 procedure TIcon.Draw(DC: HDC; X, Y: Integer);
57416 asm //cmd //opd
57417 CALL asmIconEmpty
57418 JZ @@exit
57419 PUSH DI_NORMAL
57420 PUSH 0
57421 PUSH 0
57422 PUSH [EAX].fSize
57423 PUSH [EAX].fSize
57424 PUSH [EAX].fHandle
57425 PUSH Y
57426 PUSH ECX
57427 PUSH EDX
57428 CALL DrawIconEx
57429 @@exit:
57430 end;
57431 {$ELSE ASM_VERSION} //Pascal
57432 procedure TIcon.Draw(DC: HDC; X, Y: Integer);
57433 begin
57434 if Empty then Exit;
57435 DrawIconEx( DC, X, Y, fHandle, fSize, fSize, 0, 0, DI_NORMAL );
57436 end;
57437 {$ENDIF ASM_VERSION}
57439 {$IFDEF ASM_VERSION}
57440 //[procedure TIcon.StretchDraw]
57441 procedure TIcon.StretchDraw(DC: HDC; Dest: TRect);
57442 asm //cmd //opd
57443 CALL asmIconEmpty
57444 JZ @@exit
57445 PUSH DI_NORMAL
57446 PUSH 0
57447 PUSH 0
57448 PUSH ECX
57449 PUSH ECX
57450 PUSH [EAX].fHandle
57451 PUSH [ECX].TRect.Top
57452 PUSH [ECX].TRect.Left
57453 PUSH EDX
57454 MOV EAX, [ECX].TRect.Bottom
57455 SUB EAX, [ECX].TRect.Top
57456 MOV [ESP+20], EAX
57457 MOV EAX, [ECX].TRect.Right
57458 SUB EAX, [ECX].TRect.Left
57459 MOV [ESP+16], EAX
57460 CALL DrawIconEx
57461 @@exit:
57462 end;
57463 {$ELSE ASM_VERSION} //Pascal
57464 procedure TIcon.StretchDraw(DC: HDC; Dest: TRect);
57465 begin
57466 if Empty then Exit;
57467 DrawIconEx( DC, Dest.Left, Dest.Top, FHandle, Dest.Right - Dest.Left,
57468 Dest.Bottom - Dest.Top, 0, 0, DI_NORMAL );
57469 end;
57470 {$ENDIF ASM_VERSION}
57472 //[function TIcon.GetEmpty]
57473 function TIcon.GetEmpty: Boolean;
57474 begin
57475 Result := fHandle = 0;
57476 end;
57479 //[function TIcon.GetHotSpot]
57480 function TIcon.GetHotSpot: TPoint;
57481 var II : TIconInfo;
57482 begin
57483 Result := MakePoint( 0, 0 );
57484 if FHandle = 0 then Exit;
57485 GetIconInfo( FHandle, II );
57486 Result.x := II.xHotspot;
57487 Result.y := II.yHotspot;
57488 if II.hbmMask <> 0 then
57489 DeleteObject( II.hbmMask );
57490 if II.hbmColor <> 0 then
57491 DeleteObject( II.hbmColor );
57492 end;
57495 //[procedure TIcon.LoadFromFile]
57496 procedure TIcon.LoadFromFile(const FileName: String);
57497 var Strm : PStream;
57498 begin
57499 Strm := NewReadFileStream( Filename );
57500 LoadFromStream( Strm );
57501 Strm.Free;
57502 end;
57505 //[procedure TIcon.LoadFromStream]
57506 procedure TIcon.LoadFromStream(Strm: PStream);
57507 var DesiredSize : Integer;
57508 Pos : DWord;
57509 Mem : PStream;
57510 ImgBmp, MskBmp : PBitmap;
57511 TmpBmp: PBitmap;
57512 function ReadIcon : Boolean;
57513 var IH : TIconHeader;
57514 IDI, FoundIDI : TIconDirEntry;
57515 I, SumSz, FoundSz, D : Integer;
57516 II : TIconInfo;
57517 BIH : TBitmapInfoheader;
57518 begin
57519 Result := False;
57520 if Strm.Read( IH, Sizeof( IH ) ) <> Sizeof( IH ) then Exit;
57521 if (IH.idReserved <> 0) or ((IH.idType <> 1) and (IH.idType <> 2)) or
57522 (IH.idCount < 1) then Exit;
57523 SumSz := Sizeof( IH );
57524 FoundSz := 1000;
57525 for I := 1 to IH.idCount do
57526 begin
57527 if Strm.Read( IDI, Sizeof( IDI ) ) <> Sizeof( IDI ) then Exit;
57528 if (IDI.bWidth <> IDI.bHeight) and
57529 (IDI.bWidth * 2 <> IDI.bHeight) or
57530 (IDI.bWidth = 0) {or
57531 (IDI.bReserved <> 0) or (IDI.wPlanes <> 0) or (IDI.wBitCount <> 0)} then
57532 Exit;
57533 Inc( SumSz, IDI.dwBytesInRes + Sizeof( IDI ) );
57534 D := IDI.bWidth - DesiredSize;
57535 if D < 0 then D := -D;
57536 if D < FoundSz then
57537 begin
57538 FoundSz := D;
57539 FoundIDI := IDI;
57540 end;
57541 end;
57542 if FoundSz = 1000 then Exit;
57543 Strm.Seek( Integer( Pos ) + FoundIDI.dwImageOffset, spBegin );
57544 fSize := FoundIDI.bWidth;
57546 if Strm.Read( BIH, Sizeof( BIH ) ) <> Sizeof( BIH ) then Exit;
57547 if (BIH.biWidth <> fSize) or
57548 (BIH.biHeight <> fSize * 2) and
57549 (BIH.biHeight <> fSize) then Exit;
57550 BIH.biHeight := fSize;
57552 Mem := NewMemoryStream;
57553 Mem.Write( BIH, Sizeof( BIH ) );
57554 if (FoundIDI.bColorCount >= 2) or (FoundIDI.bReserved = 1) or
57555 (FoundIDI.bColorCount = 0) then
57556 begin
57557 I := 0;
57558 if BIH.biBitCount <= 8 then
57559 I := (1 shl BIH.biBitCount) * Sizeof( TRGBQuad );
57560 if I > 0 then
57561 if Stream2Stream( Mem, Strm, I ) <> DWORD(I) then Exit;
57562 I := ((BIH.biBitCount * fSize + 31) div 32) * 4 * fSize;
57563 if Stream2Stream( Mem, Strm, I ) <> DWORD(I) then Exit;
57564 ImgBmp := NewBitmap( fSize, fSize );
57565 Mem.Seek( 0, spBegin );
57566 ImgBmp.LoadFromStream( Mem );
57567 if ImgBmp.Empty then Exit;
57568 end;
57570 BIH.biBitCount := 1;
57571 Mem.Seek( 0, spBegin );
57572 Mem.Write( BIH, Sizeof( BIH ) );
57573 I := 0;
57574 Mem.Write( I, Sizeof( I ) );
57575 I := $FFFFFF;
57576 Mem.Write( I, Sizeof( I ) );
57577 I := ((fSize + 31) div 32) * 4 * fSize;
57578 if Stream2Stream( Mem, Strm, I ) <> DWORD(I) then Exit;
57580 MskBmp := NewBitmap( fSize, fSize );
57581 Mem.Seek( 0, spBegin );
57582 MskBmp.LoadFromStream( Mem );
57583 if MskBmp.Empty then Exit;
57585 II.fIcon := True;
57586 II.xHotspot := 0;
57587 II.yHotspot := 0;
57588 II.hbmMask := MskBmp.Handle;
57589 II.hbmColor := 0;
57590 if ImgBmp <> nil then
57591 begin
57592 II.hbmColor := ImgBmp.Handle;
57593 {TmpBmp := NewBitmap( ImgBmp.Width, ImgBmp.Height );
57594 TmpBmp.HandleType := bmDIB;
57595 ImgBmp.Draw( TmpBmp.Canvas.Handle, 0, 0 );
57596 II.hbmColor := TmpBmp.Handle;}
57597 end;
57598 fHandle := CreateIconIndirect( II );
57599 //fShareIcon := False;
57600 Strm.Seek( Integer( Pos ) + SumSz, spBegin );
57601 Result := fHandle <> 0;
57602 end;
57603 begin
57604 DesiredSize := fSize;
57605 if DesiredSize = 0 then
57606 DesiredSize := GetSystemMetrics( SM_CXICON );
57607 Clear;
57608 Pos := Strm.Position;
57610 Mem := nil;
57611 ImgBmp := nil;
57612 MskBmp := nil;
57613 TmpBmp := nil;
57615 if not ReadIcon then
57616 begin
57617 Clear;
57618 Strm.Seek( Pos, spBegin );
57619 end;
57621 Mem.Free;
57622 ImgBmp.Free;
57623 MskBmp.Free;
57624 TmpBmp.Free;
57625 end;
57627 {$IFDEF ASM_VERSION}
57628 //[procedure TIcon.SaveToFile]
57629 procedure TIcon.SaveToFile(const FileName: String);
57630 asm //cmd //opd
57631 PUSH EAX
57632 MOV EAX, ESP
57633 MOV ECX, EDX
57634 XOR EDX, EDX
57635 CALL SaveIcons2File
57636 POP EAX
57637 end;
57638 {$ELSE ASM_VERSION} //Pascal
57639 procedure TIcon.SaveToFile(const FileName: String);
57640 begin
57641 SaveIcons2File( [ @Self ], FileName );
57642 end;
57643 {$ENDIF ASM_VERSION}
57645 {$IFDEF ASM_VERSION}
57646 //[procedure TIcon.SaveToStream]
57647 procedure TIcon.SaveToStream(Strm: PStream);
57648 asm //cmd //opd
57649 PUSH EAX
57650 MOV EAX, ESP
57651 MOV ECX, EDX
57652 XOR EDX, EDX
57653 CALL SaveIcons2Stream
57654 POP EAX
57655 end;
57656 {$ELSE ASM_VERSION} //Pascal
57657 procedure TIcon.SaveToStream(Strm: PStream);
57658 begin
57659 SaveIcons2Stream( [ @Self ], Strm );
57660 end;
57661 {$ENDIF ASM_VERSION}
57663 {$IFDEF ASM_noVERSION}
57664 //[procedure TIcon.SetHandle]
57665 procedure TIcon.SetHandle(const Value: HIcon);
57666 const szII = sizeof( TIconInfo );
57667 szBIH = sizeof(TBitmapInfoHeader);
57668 asm //cmd //opd
57669 CMP EDX, [EAX].fHandle
57670 JE @@exit
57671 PUSHAD
57672 PUSH EDX
57673 MOV EBX, EAX
57674 CALL Clear
57675 POP ECX
57676 MOV [EBX].fHandle, ECX
57677 JECXZ @@fin
57678 ADD ESP, -szBIH
57679 PUSH ESP
57680 PUSH ECX
57681 CALL GetIconInfo
57682 MOV ESI, [ESP].TIconInfo.hbmMask
57683 MOV EDI, [ESP].TIconInfo.hbmColor
57684 PUSH ESP
57685 PUSH szBIH
57686 PUSH ESI
57687 CALL GetObject
57688 POP EAX
57689 POP [EBX].fSize
57690 ADD ESP, szBIH-8
57691 TEST ESI, ESI
57692 JZ @@1
57693 PUSH ESI
57694 CALL DeleteObject
57695 @@1: TEST EDI, EDI
57696 JZ @@fin
57697 PUSH EDI
57698 CALL DeleteObject
57699 @@fin: POPAD
57700 @@exit:
57701 end;
57702 {$ELSE ASM_VERSION} //Pascal
57703 procedure TIcon.SetHandle(const Value: HIcon);
57704 var II : TIconInfo;
57705 B: TagBitmap;
57706 begin
57707 if FHandle = Value then Exit;
57708 Clear;
57709 FHandle := Value;
57710 if Value <> 0 then
57711 begin
57712 GetIconInfo( FHandle, II );
57713 GetObject( II.hbmMask, Sizeof( B ), @B );
57714 fSize := B.bmWidth;
57715 if II.hbmMask <> 0 then
57716 DeleteObject( II.hbmMask );
57717 if II.hbmColor <> 0 then
57718 DeleteObject( II.hbmColor );
57719 end;
57720 end;
57721 {$ENDIF ASM_VERSION}
57724 //[procedure TIcon.SetSize]
57725 procedure TIcon.SetSize(const Value: Integer);
57726 begin
57727 if FSize = Value then Exit;
57728 Clear;
57729 FSize := Value;
57730 end;
57732 const PossibleColorBits : array[1..7] of Byte = ( 1, 4, 8, 16, 24, 32, 0 );
57733 //[FUNCTION ColorBits]
57734 {$IFDEF ASM_VERSION}
57735 function ColorBits( ColorsCount : Integer ) : Integer;
57736 asm //cmd //opd
57737 PUSH EBX
57738 MOV EDX, offset[PossibleColorBits]
57739 @@loop: MOVZX ECX, byte ptr [EDX]
57740 JECXZ @@e_loop
57741 INC EDX
57742 XOR EBX, EBX
57743 INC EBX
57744 SHL EBX, CL
57745 CMP EBX, EAX
57746 JL @@loop
57747 @@e_loop:
57748 XCHG EAX, ECX
57749 POP EBX
57750 end;
57751 {$ELSE ASM_VERSION} //Pascal
57752 function ColorBits( ColorsCount : Integer ) : Integer;
57753 var I : Integer;
57754 begin
57755 for I := 1 to 6 do
57756 begin
57757 Result := PossibleColorBits[ I ];
57758 if (1 shl Result) >= ColorsCount then break;
57759 end;
57760 end;
57761 {$ENDIF ASM_VERSION}
57762 //[END ColorBits]
57764 //[function SaveIcons2StreamEx]
57765 function SaveIcons2StreamEx( const BmpHandles: array of HBitmap; Strm: PStream ): Boolean;
57766 var I, Off : Integer;
57767 IDI : TIconDirEntry;
57768 BIH : TBitmapInfoHeader;
57769 B: TagBitmap;
57770 function RGBArraySize : Integer;
57771 begin
57772 Result := 0;
57773 if (IDI.bColorCount >= 2) or (IDI.bReserved = 1) then
57774 Result := (IDI.bColorCount + (IDI.bReserved shl 8)) * Sizeof( TRGBQuad );
57775 end;
57776 function ColorDataSize( W, H: Integer ) : Integer;
57777 var N: Integer;
57778 begin
57779 if (IDI.bColorCount >= 2) or (IDI.bReserved = 1) then
57780 N := (ColorBits( IDI.bColorCount + (IDI.bReserved shl 8) ) )
57781 else
57782 begin
57783 N := IDI.wBitCount;
57784 end;
57785 Result := ((N * W + 31) div 32) * 4
57786 * H;
57787 end;
57788 function MaskDataSize( W, H: Integer ) : Integer;
57789 begin
57790 Result := ((W + 31) div 32) * 4 * H;
57791 end;
57792 var BColor, BMask: HBitmap;
57793 W, H: Integer;
57794 ImgBmp, MskBmp: PBitmap;
57795 IH : TIconHeader;
57796 Colors : PList;
57797 begin
57798 Assert( (High(BmpHandles) >= 0) and (High(BmpHandles) and 1 <> 0),
57799 'Incorrect parameters count in call to SaveIcons2StreamEx' );
57800 Result := False;
57801 IH.idReserved := 0;
57802 IH.idType := 1;
57803 IH.idCount := (High( BmpHandles )+1) div 2;
57804 if Strm.Write( IH, Sizeof( IH ) ) <> Sizeof( IH ) then Exit;
57805 Off := Sizeof( IH ) + IH.idCount * Sizeof( IDI );
57806 Colors := NewList;
57807 ImgBmp := NewBitmap( 0, 0 );
57808 MskBmp := NewBitmap( 0, 0 );
57811 for I := 0 to High( BmpHandles ) div 2 do
57812 begin
57813 BColor := BmpHandles[ I * 2 ];
57814 BMask := BmpHandles[ I * 2 + 1 ];
57815 if (BColor = 0) and (BMask = 0) then break;
57816 Assert( BMask <> 0, 'Mask bitmap not provided for saving icons in SaveIcons2StreamEx' );
57817 GetObject( BMask, Sizeof( B ), @ B );
57818 W := B.bmWidth;
57819 H := B.bmHeight;
57820 if BColor <> 0 then
57821 begin
57822 GetObject( BColor, Sizeof( B ), @B );
57823 Assert( (B.bmWidth = W) and (B.bmHeight = H),
57824 'Mask bitmap size must much color bitmap size in SaveIcons2StreamEx' );
57825 end;
57826 FillChar( IDI, Sizeof( IDI ), 0 );
57828 IDI.bWidth := W;
57829 IDI.bHeight := H;
57830 if BColor = 0 then
57831 IDI.bColorCount := 2
57832 else
57833 begin
57834 ImgBmp.Handle := CopyImage( BColor, IMAGE_BITMAP, W, H,
57835 LR_CREATEDIBSECTION );
57836 FillChar( BIH, Sizeof( BIH ), 0 );
57837 BIH.biSize := Sizeof( BIH );
57838 GetObject( ImgBmp.Handle, Sizeof( B ), @B );
57839 //if ImgBmp.HandleType = bmDDB then
57840 begin
57841 if (B.bmPlanes = 1) and (B.bmBitsPixel >= 15) then
57842 begin
57843 //ImgBmp.PixelFormat := pf24bit;
57844 IDI.bColorCount := 0;
57845 IDI.bReserved := 0;
57846 IDI.wBitCount := B.bmBitsPixel;
57848 else
57849 if B.bmPlanes * (1 shl B.bmBitsPixel) < 16 then
57850 begin
57851 ImgBmp.PixelFormat := pf1bit;
57852 IDI.bColorCount := 2;
57854 else
57855 if B.bmPlanes * (1 shl B.bmBitsPixel) < 256 then
57856 begin
57857 ImgBmp.PixelFormat := pf4bit;
57858 IDI.bColorCount := 16;
57860 else
57861 begin
57862 ImgBmp.PixelFormat := pf8bit;
57863 IDI.bColorCount := 0;
57864 IDI.bReserved := 1;
57865 end;
57866 //GetObject( ImgBmp.Handle, Sizeof( BIH ), @BIH );
57867 end;
57868 //IDI.bColorCount := (1 shl BIH.biBitCount) * BIH.biPlanes;
57869 end;
57870 Colors.Add( Pointer(IDI.bColorCount + (IDI.bReserved shl 8)) );
57871 IDI.dwBytesInRes := Sizeof( BIH ) + RGBArraySize +
57872 ColorDataSize( W, H ) + MaskDataSize( W, H );
57873 IDI.dwImageOffset := Off;
57874 if Strm.Write( IDI, Sizeof( IDI ) ) <> Sizeof( IDI ) then Exit;
57875 Inc( Off, IDI.dwBytesInRes );
57876 end;
57877 for I := 0 to High( BmpHandles ) div 2 do
57878 begin
57879 BColor := BmpHandles[ I * 2 ];
57880 BMask := BmpHandles[ I * 2 + 1 ];
57881 if (BColor = 0) and (BMask = 0) then break;
57882 GetObject( BMask, Sizeof( B ), @ B );
57883 W := B.bmWidth;
57884 H := B.bmHeight;
57886 FillChar( BIH, Sizeof( BIH ), 0 );
57887 BIH.biSize := Sizeof( BIH );
57888 BIH.biWidth := W;
57889 BIH.biHeight := H;
57890 if BColor <> 0 then
57891 BIH.biHeight := W * 2;
57892 BIH.biPlanes := 1;
57893 PWord( @ IDI.bColorCount )^ := DWord( Colors.Items[ I ] );
57894 if IDI.wBitCount = 0 then
57895 IDI.wBitCount := ColorBits( PWord( @ IDI.bColorCount )^ );
57896 BIH.biBitCount := IDI.wBitCount;
57897 BIH.biSizeImage := Sizeof( BIH ) + ColorDataSize( W, H ) + MaskDataSize( W, H );
57898 if Strm.Write( BIH, Sizeof( BIH ) ) <> Sizeof( BIH ) then Exit;
57899 if BColor <> 0 then
57900 begin
57902 ImgBmp.Handle := CopyImage( BColor, IMAGE_BITMAP, W, H, 0 );
57903 case BIH.biBitCount of
57904 1 : ImgBmp.PixelFormat := pf1bit;
57905 4 : ImgBmp.PixelFormat := pf4bit;
57906 8 : ImgBmp.PixelFormat := pf8bit;
57907 16: ImgBmp.PixelFormat := pf16bit;
57908 24: ImgBmp.PixelFormat := pf24bit;
57909 32: ImgBmp.PixelFormat := pf32bit;
57910 end;
57912 else
57913 begin
57914 ImgBmp.Handle := CopyImage( BMask, IMAGE_BITMAP, W, H, 0 );
57915 ImgBmp.PixelFormat := pf1bit;
57916 end;
57917 if ImgBmp.FDIBBits <> nil then
57918 begin
57919 if Strm.Write( Pointer(Integer(ImgBmp.FDIBHeader) + Sizeof(TBitmapInfoHeader))^,
57920 PWord( @ IDI.bColorCount )^ * Sizeof( TRGBQuad ) ) <>
57921 PWord( @ IDI.bColorCount )^ * Sizeof( TRGBQuad ) then Exit;
57922 if Strm.Write( ImgBmp.FDIBBits^, ColorDataSize( W, H ) ) <>
57923 DWord( ColorDataSize( W, H ) ) then Exit;
57924 end;
57925 MskBmp.Handle := CopyImage( BMask, IMAGE_BITMAP, W, H, 0 );
57927 MskBmp.PixelFormat := pf1bit;
57928 if Strm.Write( MskBmp.FDIBBits^, MaskDataSize( W, H ) ) <>
57929 DWord( MaskDataSize( W, H ) ) then Exit;
57930 end;
57932 FINALLY
57933 Colors.Free;
57934 ImgBmp.Free;
57935 MskBmp.Free;
57936 END;
57937 Result := True;
57938 end;
57940 {$IFDEF FPC}
57941 {$DEFINE _D3orFPC}
57942 {$ENDIF}
57943 {$IFDEF _D2orD3}
57944 {$DEFINE _D3orFPC}
57945 {$ENDIF}
57946 //[procedure SaveIcons2Stream]
57947 procedure SaveIcons2Stream( const Icons : array of PIcon; Strm : PStream );
57948 var I, J, Pos : Integer;
57949 {$IFDEF _D3orFPC}
57950 Bitmaps: array[ 0..63 ] of HBitmap;
57951 {$ELSE DELPHI}
57952 Bitmaps: array of HBitmap;
57953 {$ENDIF FPC/DELPHI}
57954 II: TIconInfo;
57955 Bmp: HBitmap;
57956 begin
57957 for I := 0 to High( Icons ) do
57958 begin
57959 if Icons[ I ].Handle = 0 then Exit;
57960 for J := I + 1 to High( Icons ) do
57961 if Icons[ I ].Size = Icons[ J ].Size then Exit;
57962 end;
57963 Pos := Strm.Position;
57965 {$IFDEF _D3orFPC}
57966 for I := 0 to High( Bitmaps ) do
57967 Bitmaps[ I ] := 0;
57968 {$ELSE DELPHI}
57969 SetLength( Bitmaps, Length( Icons ) * 2 );
57970 {$ENDIF FPC/DELPHI}
57971 for I := 0 to High( Icons ) do
57972 begin
57973 GetIconInfo( Icons[ I ].Handle, II );
57974 Bitmaps[ I * 2 ] := II.hbmColor;
57975 Bitmaps[ I * 2 + 1 ] := II.hbmMask;
57976 end;
57978 if not SaveIcons2StreamEx( Bitmaps, Strm ) then
57979 Strm.Seek( Pos, spBegin );
57981 for I := 0 to High( Bitmaps ) do
57982 begin
57983 Bmp := Bitmaps[ I ];
57984 if Bmp <> 0 then
57985 DeleteObject( Bmp );
57986 end;
57987 end;
57989 var I, J, Pos : Integer;
57990 IH : TIconHeader;
57991 Colors : PList;
57992 ImgBmp,
57993 MskBmp : PBitmap;
57994 function WriteIcons : Boolean;
57995 var I, Off : Integer;
57996 IDI : TIconDirEntry;
57997 BIH : TBitmapInfoHeader;
57998 II : TIconInfo;
57999 B: TagBitmap;
58000 function RGBArraySize : Integer;
58001 begin
58002 Result := 0;
58003 if (IDI.bColorCount >= 2) or (IDI.bReserved = 1) then
58004 Result := (IDI.bColorCount + (IDI.bReserved shl 8)) * Sizeof( TRGBQuad );
58005 end;
58006 function ColorDataSize : Integer;
58007 var N: Integer;
58008 begin
58009 //Result := 0;
58010 if (IDI.bColorCount >= 2) or (IDI.bReserved = 1) then
58011 N := (ColorBits( IDI.bColorCount + (IDI.bReserved shl 8) ) )
58012 else
58013 N := IDI.wBitCount;
58014 Result := ((N * Icons[ I ].Size + 31) div 32) * 4
58015 * Icons[ I ].Size;
58016 end;
58017 function MaskDataSize : Integer;
58018 begin
58019 Result := ((Icons[ I ].Size + 31) div 32) * 4
58020 * Icons[ I ].Size;
58021 end;
58022 begin
58023 Result := False;
58024 if Strm.Write( IH, Sizeof( IH ) ) <> Sizeof( IH ) then Exit;
58025 Off := Sizeof( IH ) + IH.idCount * Sizeof( IDI );
58026 for I := Low( Icons ) to High( Icons ) do
58027 begin
58028 FillChar( IDI, Sizeof( IDI ), 0 );
58029 IDI.bWidth := Icons[ I ].Size;
58030 IDI.bHeight := Icons[ I ].Size;
58031 GetIconInfo( Icons[ I ].Handle, II );
58032 if II.hbmColor = 0 then
58033 IDI.bColorCount := 2
58034 else
58035 begin
58036 {ImgBmp.Handle := CopyImage( II.hbmColor, IMAGE_BITMAP, Icons[ I ].Size,
58037 Icons[ I ].Size, LR_CREATEDIBSECTION );}
58038 ImgBmp.Handle := II.hbmColor;
58039 II.hbmColor := 0;
58040 FillChar( BIH, Sizeof( BIH ), 0 );
58041 BIH.biSize := Sizeof( BIH );
58042 GetObject( ImgBmp.Handle, Sizeof( B ), @B );
58043 //if ImgBmp.HandleType = bmDDB then
58044 begin
58045 if (B.bmPlanes = 1) and (B.bmBitsPixel >= 15) then
58046 begin
58047 //ImgBmp.PixelFormat := pf24bit;
58048 IDI.bColorCount := 0;
58049 IDI.bReserved := 0;
58050 IDI.wBitCount := B.bmBitsPixel;
58052 else
58053 if B.bmPlanes * (1 shl B.bmBitsPixel) < 16 then
58054 begin
58055 ImgBmp.PixelFormat := pf1bit;
58056 IDI.bColorCount := 2;
58058 else
58059 if B.bmPlanes * (1 shl B.bmBitsPixel) < 256 then
58060 begin
58061 ImgBmp.PixelFormat := pf4bit;
58062 IDI.bColorCount := 16;
58064 else
58065 begin
58066 ImgBmp.PixelFormat := pf8bit;
58067 IDI.bColorCount := 0;
58068 IDI.bReserved := 1;
58069 end;
58070 //GetObject( ImgBmp.Handle, Sizeof( BIH ), @BIH );
58071 end;
58072 //IDI.bColorCount := (1 shl BIH.biBitCount) * BIH.biPlanes;
58073 //--//DeleteObject( II.hbmColor );
58074 end;
58075 if II.hbmMask <> 0 then
58076 DeleteObject( II.hbmMask );
58077 Colors.Add( Pointer(IDI.bColorCount + (IDI.bReserved shl 8)) );
58078 IDI.dwBytesInRes := Sizeof( BIH ) + RGBArraySize +
58079 ColorDataSize + MaskDataSize;
58080 IDI.dwImageOffset := Off;
58081 if Strm.Write( IDI, Sizeof( IDI ) ) <> Sizeof( IDI ) then Exit;
58082 Inc( Off, IDI.dwBytesInRes );
58083 end;
58084 for I := Low( Icons ) to High( Icons ) do
58085 begin
58086 FillChar( BIH, Sizeof( BIH ), 0 );
58087 BIH.biSize := Sizeof( BIH );
58088 BIH.biWidth := Icons[ I ].Size;
58089 BIH.biHeight := Icons[ I ].Size;
58090 //GetObject( Icons[ I ].Handle, Sizeof( II ), @II );
58091 GetIconInfo( Icons[ I ].Handle, II );
58092 if II.hbmColor <> 0 then
58093 BIH.biHeight := Icons[ I ].Size * 2;
58094 BIH.biPlanes := 1;
58095 PWord( @ IDI.bColorCount )^ := DWord( Colors.Items[ I - Low( Icons ) ] );
58096 if IDI.wBitCount = 0 then
58097 IDI.wBitCount := ColorBits( PWord( @ IDI.bColorCount )^ );
58098 BIH.biBitCount := IDI.wBitCount;
58099 BIH.biSizeImage := Sizeof( BIH ) + ColorDataSize + MaskDataSize;
58100 if Strm.Write( BIH, Sizeof( BIH ) ) <> Sizeof( BIH ) then Exit;
58101 if II.hbmColor <> 0 then
58102 begin
58104 ImgBmp.Handle := {CopyImage( II.hbmColor, IMAGE_BITMAP, Icons[ I ].Size,
58105 Icons[ I ].Size, 0 );}
58106 II.hbmColor;
58107 II.hbmColor := 0;
58108 case BIH.biBitCount of
58109 1 : ImgBmp.PixelFormat := pf1bit;
58110 4 : ImgBmp.PixelFormat := pf4bit;
58111 8 : ImgBmp.PixelFormat := pf8bit;
58112 16: ImgBmp.PixelFormat := pf16bit;
58113 24: ImgBmp.PixelFormat := pf24bit;
58114 32: ImgBmp.PixelFormat := pf32bit;
58115 end;
58117 else
58118 begin
58119 ImgBmp.Handle := CopyImage( II.hbmMask, IMAGE_BITMAP, Icons[ I ].Size,
58120 Icons[ I ].Size, 0 );
58121 ImgBmp.PixelFormat := pf1bit;
58122 end;
58123 if ImgBmp.FDIBBits <> nil then
58124 begin
58125 if Strm.Write( Pointer(Integer(ImgBmp.FDIBHeader) + Sizeof(TBitmapInfoHeader))^,
58126 PWord( @ IDI.bColorCount )^ * Sizeof( TRGBQuad ) ) <>
58127 PWord( @ IDI.bColorCount )^ * Sizeof( TRGBQuad ) then Exit;
58128 if Strm.Write( ImgBmp.FDIBBits^, ColorDataSize ) <>
58129 DWord( ColorDataSize ) then Exit;
58130 end;
58131 MskBmp.Handle := CopyImage( II.hbmMask, IMAGE_BITMAP, Icons[ I ].Size,
58132 Icons[ I ].Size, 0 {LR_COPYRETURNORG} );
58133 //***
58134 if II.hbmMask <> 0 then
58135 DeleteObject( II.hbmMask );
58136 if II.hbmColor <> 0 then
58137 DeleteObject( II.hbmColor );
58138 //***
58140 MskBmp.PixelFormat := pf1bit;
58141 if Strm.Write( MskBmp.FDIBBits^, MaskDataSize ) <>
58142 DWord( MaskDataSize ) then Exit;
58143 end;
58144 Result := True;
58145 end;
58146 begin
58147 for I := Low( Icons ) to High( Icons ) do
58148 begin
58149 if Icons[ I ].Handle = 0 then Exit;
58150 for J := I + 1 to High( Icons ) do
58151 if Icons[ I ].Size = Icons[ J ].Size then Exit;
58152 end;
58153 IH.idReserved := 0;
58154 IH.idType := 1;
58155 IH.idCount := High( Icons ) - Low( Icons ) + 1;
58156 Pos := Strm.Position;
58157 Colors := NewList;
58158 ImgBmp := NewBitmap( 0, 0 );
58159 MskBmp := NewBitmap( 0, 0 );
58161 if not WriteIcons then
58162 Strm.Seek( Pos, spBegin );
58164 ImgBmp.Free;
58165 MskBmp.Free;
58166 Colors.Free;
58167 end;
58170 //[procedure SaveIcons2File]
58171 procedure SaveIcons2File( const Icons : array of PIcon; const FileName : String );
58172 var Strm: PStream;
58173 begin
58174 Strm := NewWriteFileStream( FileName );
58175 SaveIcons2Stream( Icons, Strm );
58176 Strm.Free;
58177 end;
58179 //[procedure TIcon.LoadFromExecutable]
58180 procedure TIcon.LoadFromExecutable(const FileName: String; IconIdx: Integer);
58181 var I: Integer;
58182 begin
58183 Clear;
58184 I := ExtractIcon( hInstance, PChar( FileName ), IconIdx );
58185 if I > 1 then
58186 Handle := I;
58187 end;
58189 //[function GetFileIconCount]
58190 function GetFileIconCount( const FileName: String ): Integer;
58191 begin
58192 Result := ExtractIcon( hInstance, PChar( FileName ), DWORD(-1) );
58193 end;
58195 //[procedure TIcon.LoadFromResourceID]
58196 procedure TIcon.LoadFromResourceID(Inst, ResID, DesiredSize: Integer);
58197 begin
58198 LoadFromResourceName( Inst, MAKEINTRESOURCE( ResID ), DesiredSize );
58199 end;
58201 //[procedure TIcon.LoadFromResourceName]
58202 procedure TIcon.LoadFromResourceName(Inst: Integer; ResName: PChar; DesiredSize: Integer);
58203 begin
58204 Handle := LoadImage( Inst, ResName, IMAGE_ICON, DesiredSize, DesiredSize,
58205 $8000 {LR_SHARED} );
58206 {if Handle = 0 then
58207 Handle := LoadIcon( Inst, ResName )
58208 else}
58209 if fHandle <> 0 then FShareIcon := True;
58210 end;
58212 //[function LoadImgIcon]
58213 function LoadImgIcon( RsrcName: PChar; Size: Integer ): HIcon;
58214 begin
58215 Result := LoadImage( hInstance, RsrcName, IMAGE_ICON, Size, Size, $8000 {LR_SHARED} );
58216 end;
58219 ////////////////////////////////////////////////////////////////////////
58222 // M E T A F I L E
58225 ////////////////////////////////////////////////////////////////////////
58227 {++}(*
58228 //[API SetEnhMetaFileBits]
58229 function SetEnhMetaFileBits; external gdi32 name 'SetEnhMetaFileBits';
58230 function PlayEnhMetaFile; external gdi32 name 'PlayEnhMetaFile';
58231 *){--}
58233 //[function NewMetafile]
58234 function NewMetafile: PMetafile;
58235 begin
58237 new( Result, Create );
58238 {+}{++}(*Result := PMetafile.Create;*){--}
58239 end;
58240 //[END NewMetafile]
58242 { TMetafile }
58244 //[procedure TMetafile.Clear]
58245 procedure TMetafile.Clear;
58246 begin
58247 if fHandle <> 0 then
58248 DeleteEnhMetaFile( fHandle );
58249 fHandle := 0;
58250 end;
58252 //[destructor TMetafile.Destroy]
58253 destructor TMetafile.Destroy;
58254 begin
58255 if fHeader <> nil then
58256 FreeMem( fHeader );
58257 Clear;
58258 inherited;
58259 end;
58261 //[procedure TMetafile.Draw]
58262 procedure TMetafile.Draw(DC: HDC; X, Y: Integer);
58263 begin
58264 StretchDraw( DC, MakeRect( X, Y, X + Width, Y + Height ) );
58265 end;
58267 //[function TMetafile.Empty]
58268 function TMetafile.Empty: Boolean;
58269 begin
58270 Result := fHandle = 0;
58271 end;
58273 //[function TMetafile.GetHeight]
58274 function TMetafile.GetHeight: Integer;
58275 begin
58276 Result := 0;
58277 if Empty then Exit;
58278 RetrieveHeader;
58279 Result := fHeader.rclBounds.Bottom - fHeader.rclBounds.Top;
58280 end;
58282 //[function TMetafile.GetWidth]
58283 function TMetafile.GetWidth: Integer;
58284 begin
58285 Result := 0;
58286 if Empty then Exit;
58287 RetrieveHeader;
58288 Result := fHeader.rclBounds.Right - fHeader.rclBounds.Left;
58289 end;
58291 //[function TMetafile.LoadFromFile]
58292 function TMetafile.LoadFromFile(const Filename: String): Boolean;
58293 var Strm: PStream;
58294 begin
58295 Strm := NewReadFileStream( FileName );
58296 Result := LoadFromStream( Strm );
58297 Strm.Free;
58298 end;
58300 //[function ComputeAldusChecksum]
58301 function ComputeAldusChecksum(var WMF: TMetafileHeader): Word;
58302 type
58303 PWord = ^Word;
58305 pW: PWord;
58306 pEnd: PWord;
58307 begin
58308 Result := 0;
58309 pW := @WMF;
58310 pEnd := @WMF.CheckSum;
58311 while Longint(pW) < Longint(pEnd) do
58312 begin
58313 Result := Result xor pW^;
58314 Inc(Longint(pW), SizeOf(Word));
58315 end;
58316 end;
58318 //[function TMetafile.LoadFromStream]
58319 function TMetafile.LoadFromStream(Strm: PStream): Boolean;
58320 var WMF: TMetaFileHeader;
58321 WmfHdr: TMetaHeader;
58322 EnhHdr: TEnhMetaHeader;
58323 Pos, Pos1: Integer;
58324 Sz: Integer;
58325 MemStrm: PStream;
58326 MFP: TMetafilePict;
58327 begin
58328 Result := FALSE;
58329 Pos := Strm.Position;
58331 if Strm.Read( WMF, Sizeof( WMF ) ) <> Sizeof( WMF ) then
58332 begin
58333 Strm.Position := Pos;
58334 Exit;
58335 end;
58337 MemStrm := NewMemoryStream;
58339 if WMF.Key = WMFKey then
58340 begin // Windows metafile
58342 if WMF.CheckSum <> ComputeAldusChecksum( WMF ) then
58343 begin
58344 Strm.Position := Pos;
58345 Exit;
58346 end;
58348 Pos1 := Strm.Position;
58349 if Strm.Read( WmfHdr, Sizeof( WmfHdr ) ) <> Sizeof( WmfHdr ) then
58350 begin
58351 Strm.Position := Pos;
58352 Exit;
58353 end;
58355 Strm.Position := Pos1;
58356 Sz := WMFHdr.mtSize * 2;
58357 Stream2Stream( MemStrm, Strm, Sz );
58358 FillChar( MFP, Sizeof( MFP ), 0 );
58359 MFP.mm := MM_ANISOTROPIC;
58360 fHandle := SetWinMetafileBits( Sz, MemStrm.Memory, 0, MFP );
58363 else
58364 begin // may be enchanced?
58366 Strm.Position := Pos;
58367 if Strm.Read( EnhHdr, Sizeof( EnhHdr ) ) < 8 then
58368 begin
58369 Strm.Position := Pos;
58370 Exit;
58371 end;
58372 // yes, enchanced
58373 Strm.Position := Pos;
58374 Sz := EnhHdr.nBytes;
58375 Stream2Stream( MemStrm, Strm, Sz );
58376 fHandle := SetEnhMetaFileBits( Sz, MemStrm.Memory );
58378 end;
58380 MemStrm.Free;
58381 Result := fHandle <> 0;
58382 if not Result then
58383 Strm.Position := Pos;
58385 end;
58387 //[procedure TMetafile.RetrieveHeader]
58388 procedure TMetafile.RetrieveHeader;
58389 var SzHdr: Integer;
58390 begin
58391 if fHeader <> nil then
58392 FreeMem( fHeader );
58393 SzHdr := GetEnhMetaFileHeader( fHandle, 0, nil );
58394 GetMem( fHeader, SzHdr );
58395 GetEnhMetaFileHeader( fHandle, SzHdr, fHeader );
58396 end;
58398 //[procedure TMetafile.SetHandle]
58399 procedure TMetafile.SetHandle(const Value: THandle);
58400 begin
58401 Clear;
58402 fHandle := Value;
58403 end;
58405 //[procedure TMetafile.StretchDraw]
58406 procedure TMetafile.StretchDraw(DC: HDC; const R: TRect);
58407 begin
58408 if Empty then Exit;
58409 PlayEnhMetaFile( DC, fHandle, R );
58410 end;
58424 //[procedure AlignChildrenProc]
58425 procedure AlignChildrenProc( Sender: PObj );
58426 type
58427 TAligns = set of TControlAlign;
58428 var P: PControl;
58429 CR: TRect;
58430 procedure DoAlign( Allowed: TAligns );
58431 var I: Integer;
58432 C: PControl;
58433 R, R1: TRect;
58434 W, H: Integer;
58435 ChgPos, ChgSiz: Boolean;
58436 begin
58437 for I := 0 to P.fChildren.fCount - 1 do
58438 begin
58439 C := P.fChildren.fItems[ I ];
58440 if not C.ToBeVisible then continue;
58441 // important: not fVisible, and even not Visible, but ToBeVisible!
58442 if C.fNotUseAlign then continue;
58443 if C.FAlign in Allowed then
58444 begin
58445 R := C.BoundsRect;
58446 R1 := R;
58447 W := R.Right - R.Left;
58448 H := R.Bottom - R.Top;
58449 case C.FAlign of
58450 caTop:
58451 begin
58452 OffsetRect( R, 0, -R.Top + CR.Top + P.Margin );
58453 Inc( CR.Top, H + P.Margin );
58454 R.Left := CR.Left + P.Margin;
58455 R.Right := CR.Right - P.Margin;
58456 end;
58457 caBottom:
58458 begin
58459 OffsetRect( R, 0, -R.Bottom + CR.Bottom - P.Margin );
58460 Dec( CR.Bottom, H + P.Margin );
58461 R.Left := CR.Left + P.Margin;
58462 R.Right := CR.Right - P.Margin;
58463 end;
58464 caLeft:
58465 begin
58466 OffsetRect( R, -R.Left + CR.Left + P.Margin, 0 );
58467 Inc( CR.Left, W + P.Margin );
58468 R.Top := CR.Top + P.Margin;
58469 R.Bottom := CR.Bottom - P.Margin;
58470 end;
58471 caRight:
58472 begin
58473 OffsetRect( R, -R.Right + CR.Right - P.Margin, 0 );
58474 Dec( CR.Right, W + P.Margin );
58475 R.Top := CR.Top + P.Margin;
58476 R.Bottom := CR.Bottom - P.Margin;
58477 end;
58478 caClient:
58479 begin
58480 R := CR;
58481 InflateRect( R, -P.Margin, -P.Margin );
58482 end;
58483 end;
58484 if R.Right < R.Left then R.Right := R.Left;
58485 if R.Bottom < R.Top then R.Bottom := R.Top;
58486 ChgPos := (R.Left <> R1.Left) or (R.Top <> R1.Top);
58487 ChgSiz := (R.Right - R.Left <> W) or (R.Bottom - R.Top <> H);
58488 if ChgPos or ChgSiz then
58489 begin
58490 C.BoundsRect := R;
58491 if ChgSiz then
58492 AlignChildrenProc( C );
58493 end;
58494 end;
58495 end;
58496 end;
58497 begin
58498 P := Pointer( Sender );
58499 if P = nil then Exit; // Called for form - ignore.
58500 CR := P.ClientRect;
58501 DoAlign( [ caTop, caBottom ] );
58502 DoAlign( [ caLeft, caRight ] );
58503 DoAlign( [ caClient ] );
58504 end;
58507 //[procedure TControl.Set_Align]
58508 procedure TControl.Set_Align(const Value: TControlAlign);
58509 begin
58510 Global_Align := AlignChildrenProc;
58511 if fNotUseAlign then Exit;
58512 if FAlign = Value then Exit;
58513 FAlign := Value;
58514 //Global_Align( Parent );
58515 AlignChildrenProc( Parent );
58516 end;
58519 //[function TControl.SetAlign]
58520 function TControl.SetAlign(AAlign: TControlAlign): PControl;
58521 begin
58522 Set_Align( AAlign );
58523 Result := @Self;
58524 end;
58527 //[function WndProcPreventResizeFlicks]
58528 function WndProcPreventResizeFlicks( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
58529 type TRectsArray = array[0..2] of TRect;
58530 PRectsArray = ^TRectsArray;
58531 TChange = ( ChgL, ChgT, ChgR, ChgB );
58532 TChanges = Set of TChange;
58533 var Rects : PRectsArray;
58534 Changes : Set of TChange;
58535 Resizing : Boolean;
58536 X, Y, DX, DY : Integer;
58537 EntireRect, Src, Dst : TRect;
58539 function GetClientAfter : TRect;
58540 var R : TRect;
58541 begin
58542 R := Rects[ 2 ];
58543 OffsetRect( R, Rects[ 0 ].Left - Rects[ 1 ].Left,
58544 Rects[ 0 ].Top - Rects[ 1 ].Top );
58545 if Rects[ 0 ].Right - Rects[ 0 ].Left <> Rects[ 1 ].Right - Rects[ 1 ].Left then
58546 R.Right := R.Left + (R.Right - R.Left)
58547 + (Rects[ 0 ].Right - Rects[ 0 ].Left)
58548 - (Rects[ 1 ].Right - Rects[ 1 ].Left);
58549 if Rects[ 0 ].Bottom - Rects[ 0 ].Top <> Rects[ 1 ].Bottom - Rects[ 1 ].Top then
58550 R.Bottom := R.Top + (R.Bottom - R.Top)
58551 + (Rects[ 0 ].Bottom - Rects[ 0 ].Top)
58552 - (Rects[ 1 ].Bottom - Rects[ 1 ].Top);
58553 Result := R;
58554 end;
58556 procedure DoResize( F : PControl; Changes : TChanges );
58557 var ClientAfter : TRect;
58559 procedure CollectClipRgn( V : PControl; Changes : TChanges );
58560 var C : PControl;
58561 I : Integer;
58562 begin
58563 for I := 0 to V.FChildren.FCount - 1 do
58564 begin
58565 C := V.FChildren.FItems[ I ];
58566 if not C.Visible then Continue;
58568 if C.fNotUseAlign then
58569 begin
58570 C.Update;
58571 end;
58572 end;
58573 end; // of CollectClipRgn
58576 begin // DoResize
58577 ClientAfter := GetClientAfter;
58578 //ClipRgn := CreateRectRgn( ClientAfter.Left, ClientAfter.Top,
58579 // ClientAfter.Right, ClientAfter.Bottom );
58580 CollectClipRgn( F, Changes );
58581 //ScrollWithoutClipRgn;
58582 //DeleteObject( ClipRgn );
58583 end; // of DoResize
58585 var PR: PRect;
58586 R: TRect;
58587 begin // Procedure WndProcResizeFlicks
58588 Result := False;
58589 case Msg.message of
58590 WM_NCCALCSIZE:
58591 if Msg.wParam <> 0 then
58592 begin
58593 Rects := Pointer( Msg.lParam );
58594 Changes := [];
58595 if Rects[ 0 ].Left <> Rects[ 1 ].Left then
58596 Changes := Changes + [ ChgL ];
58597 if Rects[ 0 ].Top <> Rects[ 1 ].Top then
58598 Changes := Changes + [ ChgT ];
58599 if Rects[ 0 ].Right <> Rects[ 1 ].Right then
58600 Changes := Changes + [ ChgR ];
58601 if Rects[ 0 ].Bottom <> Rects[ 1 ].Bottom then
58602 Changes := Changes + [ ChgB ];
58603 Resizing := Changes * [ ChgL, ChgT ] <> [ ];
58604 if Resizing and not Sender.fNotUseAlign then
58605 begin
58606 EntireRect := GetClientAfter;
58607 OffsetRect( EntireRect, -EntireRect.Left, -EntireRect.Top );
58608 if EntireRect.Right - EntireRect.Left < Rects[ 2 ].Right - Rects[ 2 ].Left then
58609 EntireRect.Right := Rects[ 2 ].Right - Rects[ 2 ].Left;
58610 if EntireRect.Bottom - EntireRect.Top < Rects[ 2 ].Bottom - Rects[ 2 ].Top then
58611 EntireRect.Bottom := Rects[ 2 ].Bottom - Rects[ 2 ].Top;
58612 X := Min( Rects[ 0 ].Left, Rects[ 1 ].Left ) + Rects[ 2 ].Left - Rects[ 1 ].Left;
58613 Y := Min( Rects[ 0 ].Top, Rects[ 1 ].Top ) + Rects[ 2 ].Top - Rects[ 2 ].Top;
58614 OffsetRect( EntireRect, X, Y );
58615 DX := 0; DY := 0;
58616 if ChgL in Changes then
58617 DX := Rects[ 0 ].Left - Rects[ 1 ].Left;
58618 if ChgR in Changes then
58619 DX := Rects[ 0 ].Right - Rects[ 1 ].Right;
58620 if ChgT in Changes then
58621 DY := Rects[ 0 ].Top - Rects[ 1 ].Top;
58622 if ChgB in Changes then
58623 DY := Rects[ 0 ].Bottom - Rects[ 1 ].Bottom;
58624 DoResize( Sender, Changes );
58625 if (Changes = [ChgL]) {and (Rects[0].Left <> Rects[1].Left)} then
58626 begin
58627 Rslt := WVR_VALIDRECTS;
58628 Src := Rects[ 2 ];
58629 Dst := GetClientAfter;
58630 Src.Right := Src.Left - DX;
58631 Dst.Right := Dst.Left - DX;
58632 Rects[ 1 ] := Src;
58633 Rects[ 2 ] := Dst;
58635 else
58636 if (Changes = [ChgR]) {and (Rects[0].Right > Rects[1].Right)} then
58637 begin
58638 Rslt := WVR_VALIDRECTS;
58639 Src := Rects[ 2 ];
58640 Dst := GetClientAfter;
58641 Src.Left := Src.Right - DX;
58642 Dst.Left := Dst.Right - DX;
58643 Rects[ 1 ] := Src;
58644 Rects[ 2 ] := Dst;
58646 else
58647 if (Changes = [ChgT]) {and (Rects[0].Top <> Rects[1].Top)} then
58648 begin
58649 Rslt := WVR_VALIDRECTS;
58650 Src := Rects[ 2 ];
58651 Dst := GetClientAfter;
58652 Src.Bottom := Src.Top - DY;
58653 Dst.Bottom := Dst.Top - DY;
58654 Rects[ 1 ] := Src;
58655 Rects[ 2 ] := Dst;
58657 else
58658 if Changes = [ChgL,ChgT] then
58659 begin
58660 Rslt := WVR_VALIDRECTS;
58661 Src := Rects[ 2 ];
58662 Dst := GetClientAfter;
58663 Src.Left := Src.Right - DX;
58664 Dst.Left := Dst.Right - DX;
58665 Src.Bottom := Src.Top - DY;
58666 Dst.Bottom := Dst.Top - DY;
58667 Rects[ 1 ] := Src;
58668 Rects[ 2 ] := Dst;
58669 end;
58670 PostMessage( Sender.fHandle, CM_UPDATE, 0, 0 );
58672 {else
58673 if Sender.fNotUseAlign then
58674 begin
58675 end};
58676 end;
58677 CM_UPDATE:
58678 begin
58679 if Sender.fNotUpdate then
58680 begin
58681 Sender.fNotUpdate := False;
58682 Sender.Invalidate;
58683 end;
58684 Sender.Update;
58685 end;
58686 WM_SIZING:
58687 begin
58688 if (Msg.wParam = WMSZ_TOPLEFT) or (Msg.wParam = WMSZ_BOTTOMLEFT) or (Msg.wParam = WMSZ_TOPRIGHT) then
58689 begin
58690 PR := Pointer( Msg.lParam );
58691 GetWindowRect( Sender.fHandle, R );
58692 PostMessage( Sender.fHandle, CM_SIZEPOS, LoWord( PR.Left) or (PR.Top shl 16),
58693 LoWord( PR.Right - PR.Left ) or ( (PR.Bottom - PR.Top) shl 16) );
58694 if Msg.wParam = WMSZ_TOPLEFT then
58695 if Abs( R.Top - PR.Top ) < Abs( R.Left - PR.Left ) then
58696 PR.Top := R.Top
58697 else
58698 PR.Left := R.Left
58699 else
58700 if Msg.wParam = WMSZ_BOTTOMLEFT then
58701 if Abs( R.Bottom - PR.Bottom ) < Abs( R.Left - PR.Left ) then
58702 PR.Bottom := R.Bottom
58703 else
58704 PR.Left := R.Left
58705 else // WMSZ_TOPRIGHT
58706 if Abs( R.Top - PR.Top ) < Abs( R.Right - PR.Right ) then
58707 PR.Top := R.Top
58708 else
58709 PR.Right := R.Right;
58710 Sender.fNotUpdate := True;
58711 Rslt := 1;
58712 Result := TRUE;
58713 end;
58714 end;
58715 CM_SIZEPOS:
58716 begin
58717 Sender.fNotUpdate := False;
58718 SetWindowPos( Sender.fHandle, 0, SmallInt( LoWord( Msg.wParam ) ),
58719 SmallInt( HiWord( Msg.wParam ) ), SmallInt( LoWord( Msg.lParam ) ),
58720 SmallInt( HiWord( Msg.lParam ) ), SWP_NOZORDER or SWP_NOACTIVATE );
58721 end;
58722 WM_PAINT:
58723 begin
58724 if Sender.fNotUpdate then
58725 begin
58726 Rslt := 0;
58727 Result := True;
58728 end;
58729 end;
58730 WM_ERASEBKGND:
58731 begin
58732 if Sender.fNotUpdate then
58733 begin
58734 Rslt := 1;
58735 Result := True;
58736 end;
58737 end;
58738 end;
58739 end;
58742 //[function TControl.PreventResizeFlicks]
58743 function TControl.PreventResizeFlicks: PControl;
58744 begin
58745 fWndProcResizeFlicks := WndProcPreventResizeFlicks;
58746 Result := @Self;
58747 end;
58750 //[procedure TControl.Update]
58751 procedure TControl.Update;
58752 var I: Integer;
58753 C: PControl;
58754 begin
58755 if fUpdateCount > 0 then
58756 Exit;
58757 if fNotUpdate then Exit;
58758 if fHandle = 0 then Exit;
58759 UpdateWindow( fHandle );
58760 for I := 0 to fChildren.fCount - 1 do
58761 begin
58762 C := fChildren.fItems[ I ];
58763 C.Update;
58764 end;
58765 end;
58767 //[FUNCTION WndProcUpdate]
58768 {$IFDEF ASM_VERSION}
58769 function WndProcUpdate( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
58770 asm //cmd //opd
58771 PUSH EBX
58772 XCHG EBX, EAX
58773 MOV EAX, [EBX].TControl.fUpdateCount
58774 TEST EAX, EAX
58775 JZ @@exit
58777 XOR EAX, EAX
58778 MOV EDX, [EDX].TMsg.message
58779 CMP DX, WM_PAINT
58780 JNE @@chk_erasebkgnd
58782 MOV [ECX], EAX
58783 PUSH EAX
58784 PUSH [EBX].TControl.fHandle
58785 CALL ValidateRect
58786 JMP @@rslt_1
58787 @@chk_erasebkgnd:
58788 CMP DX, WM_ERASEBKGND
58789 JNE @@exit
58790 INC EAX
58791 MOV [ECX], EAX
58792 @@rslt_1:
58793 MOV AL, 1
58794 @@exit:
58795 POP EBX
58796 end;
58797 {$ELSE ASM_VERSION} //Pascal
58798 function WndProcUpdate( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
58799 begin
58800 if Sender.fUpdateCount > 0 then
58801 begin
58802 case Msg.message of
58803 WM_PAINT:
58804 begin
58805 ValidateRect( Sender.Handle, nil );
58806 Rslt := 0;
58807 end;
58808 WM_ERASEBKGND: Rslt := 1;
58809 else begin
58810 Result := FALSE;
58811 Exit;
58812 end;
58813 end;
58814 Result := TRUE;
58816 else Result := FALSE;
58817 end;
58818 {$ENDIF ASM_VERSION}
58819 //[END WndProcUpdate]
58821 //[procedure TControl.BeginUpdate]
58822 procedure TControl.BeginUpdate;
58823 begin
58824 Inc( fUpdateCount );
58825 AttachProc( @WndProcUpdate );
58826 end;
58828 //[procedure TControl.EndUpdate]
58829 procedure TControl.EndUpdate;
58830 begin
58831 Dec( fUpdateCount );
58832 if fUpdateCount <= 0 then
58833 begin
58834 Invalidate;
58835 //Update;
58836 end;
58837 end;
58840 //[function TControl.GetSelection]
58841 function TControl.GetSelection: String;
58842 var L: Integer;
58843 begin
58844 if fCommandActions.aGetSelection <> 0 then
58845 begin
58846 L := SelLength;
58847 SetString( Result, nil, L + 1 );
58848 Perform( fCommandActions.aGetSelection, 0, Integer( @Result[ 1 ] ) );
58850 else
58851 Result := Copy( Text, SelStart + 1, SelLength );
58852 end;
58855 //[procedure TControl.SetSelection]
58856 procedure TControl.SetSelection(const Value: String);
58857 begin
58858 ReplaceSelection( Value, True );
58859 end;
58862 //[procedure TControl.ReplaceSelection]
58863 procedure TControl.ReplaceSelection(const Value: String; aCanUndo: Boolean);
58864 begin
58865 if fCommandActions.aReplaceSel <> 0 then
58866 begin
58867 Perform( fCommandActions.aReplaceSel, Integer( aCanUndo ), Integer( Pchar( Value ) ) );
58868 end;
58869 end;
58871 //[procedure TControl.DeleteLines]
58872 procedure TControl.DeleteLines(FromLine, ToLine: Integer);
58873 var I1, I2: Integer;
58874 SStart, SLength: Integer;
58875 begin
58876 if FromLine > ToLine then Exit;
58877 Assert( FromLine >= 0, 'Incorrect line index' );
58878 I1 := Item2Pos( FromLine );
58879 I2 := Item2Pos( ToLine+1 );
58880 SStart := SelStart;
58881 SLength := SelLength;
58882 SelStart := I1;
58883 SelLength := I2 - I1;
58884 ReplaceSelection( '', TRUE );
58885 if SStart >= I2 then
58886 begin
58887 SStart := SStart - (I2 - I1);
58889 else
58890 if SStart >= I1 then
58891 begin
58892 SLength := SLength - (I2 - SStart);
58893 SStart := I1;
58895 else
58896 if SStart + SLength >= I2 then
58897 begin
58898 SLength := SLength - (I2 - I1);
58900 else
58901 if SStart + SLength >= I1 then
58902 begin
58903 SLength := I1 - SLength;
58904 end;
58905 SelStart := SStart;
58906 SelLength := Max( 0, SLength );
58907 end;
58910 //[procedure TControl.SetTabOrder]
58911 procedure TControl.SetTabOrder(const Value: Integer);
58912 var CL: PList;
58913 I : Integer;
58914 C: PControl;
58915 begin
58916 if Value = fTabOrder then Exit;
58917 CL := CollectTabControls( ParentForm );
58918 for I := 0 to CL.fCount - 1 do
58919 begin
58920 C := CL.fItems[ I ];
58921 if C.fTabOrder >= Value then
58922 Inc( C.fTabOrder );
58923 end;
58924 fTabOrder := Value;
58925 CL.Free;
58926 end;
58929 //[function TControl.GetFocused]
58930 function TControl.GetFocused: Boolean;
58931 begin
58932 if fIsControl then
58933 Result := ParentForm.fCurrentControl = @Self
58934 else
58935 Result := GetForegroundWindow = fHandle;
58936 end;
58939 //[procedure TControl.SetFocused]
58940 procedure TControl.SetFocused(const Value: Boolean);
58941 begin
58942 if not Value then Exit;
58943 if fIsControl then
58944 begin
58945 ParentForm.fCurrentControl := @Self;
58946 SetFocus( GetWindowHandle );
58948 else
58949 begin
58950 SetForegroundWindow( GetWindowHandle );
58951 end;
58952 end;
58954 type
58955 PCharFormat = ^TCharFormat;
58962 //////////////////////////////////////////////////////////////////////
58965 // R I C H E D I T
58968 //////////////////////////////////////////////////////////////////////
58970 { -- rich edit -- }
58973 //[function TControl.REGetFont]
58974 function TControl.REGetFont: PGraphicTool;
58975 var CF: PCharFormat;
58976 FS: TFontStyle;
58977 begin
58978 CF := @fRECharFormatRec;
58979 FillChar( CF^, 82 {sizeof( TCharFormat2 )}, 0 );
58980 CF.cbSize := sizeof( RichEdit.TCharFormat ) + fCharFmtDeltaSz;
58981 if fTmpFont = nil then
58982 fTmpFont := NewFont;
58983 Result := fTmpFont;
58984 Result.OnChange := nil;
58985 Perform( EM_GETCHARFORMAT, 1, Integer( CF ) );
58986 Result.FontHeight := CF.yHeight;
58987 FS := [ ];
58988 if LongBool(CF.dwEffects and CFE_BOLD) then
58989 FS := [ fsBold ];
58990 if LongBool(CF.dwEffects and CFE_ITALIC) then
58991 FS := FS + [ fsItalic ];
58992 if LongBool(CF.dwEffects and CFE_STRIKEOUT) then
58993 FS := FS + [ fsStrikeOut ];
58994 if LongBool(CF.dwEffects and CFE_UNDERLINE) then
58995 FS := FS + [ fsUnderline ];
58996 Result.FontStyle := FS;
58997 if not LongBool(CF.dwEffects and CFE_AUTOCOLOR) then
58998 Result.Color := CF.crTextColor;
58999 Result.FontPitch := TFontPitch( CF.bPitchAndFamily and 3 );
59000 Result.FontCharset := CF.bCharSet;
59001 Result.FontName := CF.szFaceName;
59002 Result.OnChange := RESetFont;
59003 end;
59005 const RichAreas: array[ TRichFmtArea ] of Integer = ( SCF_SELECTION,
59006 SCF_WORD, 4 {SCF_ALL} );
59009 //[procedure TControl.RESetFontEx]
59010 procedure TControl.RESetFontEx(const Index: Integer);
59011 var CF: PCharFormat;
59012 FS: TFontStyle;
59013 begin
59014 CF := @fRECharFormatRec;
59015 FillChar( CF^, {82} sizeof( TCharFormat2 ), 0 );
59016 CF.cbSize := 60 { sizeof( TCharFormat ) } + fCharFmtDeltaSz;
59017 CF.dwMask := CFM_BOLD or CFM_COLOR or CFM_FACE or CFM_ITALIC
59018 or CFM_SIZE or CFM_STRIKEOUT or CFM_UNDERLINE;
59019 CF.yHeight := fTmpFont.FontHeight;
59020 FS := fTmpFont.FontStyle;
59021 if fsBold in FS then CF.dwEffects := CFE_BOLD;
59022 if fsItalic in FS then CF.dwEffects := CF.dwEffects or CFE_ITALIC;
59023 if fsStrikeOut in FS then CF.dwEffects := CF.dwEffects or CFE_STRIKEOUT;
59024 if fsUnderline in FS then CF.dwEffects := CF.dwEffects or CFE_UNDERLINE;
59025 CF.crTextColor := Color2RGB(fTmpFont.Color);
59026 CF.bCharSet := fTmpFont.FontCharset;
59027 CF.bPitchAndFamily := Ord( fTmpFont.FontPitch );
59028 StrLCopy( CF.szFaceName, PChar( fTmpFont.FontName ), 31 );
59029 Perform( EM_SETCHARFORMAT, RichAreas[ fRECharArea ], Integer( CF ) );
59030 end;
59033 //[procedure TControl.RESetFont]
59034 procedure TControl.RESetFont(Value: PGraphicTool);
59035 var H: Integer;
59036 begin
59037 if Value <> fTmpFont then
59038 REGetFont;
59039 H := fTmpFont.fData.Font.Height;
59040 fTmpFont := fTmpFont.Assign( Value );
59041 if fTmpFont.fData.Font.Height = 0 then
59042 fTmpFont.fData.Font.Height := H;
59043 RESetFontEx( Integer( CFM_BOLD or CFM_COLOR or CFM_FACE or CFM_ITALIC
59044 or CFM_SIZE or CFM_STRIKEOUT or CFM_UNDERLINE ) );
59045 end;
59048 //[function TControl.REGetFontMask]
59049 function TControl.REGetFontMask( const Index: Integer ): Boolean;
59050 begin
59051 REGetFont;
59052 Result := LongBool( fRECharFormatRec.dwMask and Index );
59053 end;
59056 //[function TControl.REGetFontEffects]
59057 function TControl.REGetFontEffects(const Index: Integer): Boolean;
59058 begin
59059 REGetFont;
59060 Result := LongBool( fRECharFormatRec.dwEffects and Index );
59061 end;
59064 //[procedure TControl.RESetFontEffect]
59065 procedure TControl.RESetFontEffect(const Index: Integer;
59066 const Value: Boolean);
59067 var CF: PCharFormat;
59068 begin
59069 ReGetFont;
59070 CF := @fRECharFormatRec;
59071 CF.dwEffects := $FFFFFFFF and Index;
59072 if not Value then CF.dwEffects := 0;
59073 CF.dwMask := Index;
59074 Perform( EM_SETCHARFORMAT, RichAreas[ fRECharArea ], Integer( CF ) );
59075 end;
59078 //[function TControl.REGetFontAttr]
59079 function TControl.REGetFontAttr(const Index: Integer): Integer;
59080 var CF: PDWORD;
59081 Mask: DWORD;
59082 begin
59083 REGetFont;
59084 CF := Pointer( Integer( @fRECharFormatRec ) + (HiWord(Index) and $7E) );
59085 Mask := $FFFFFFFF;
59086 if LongBool( HiWord(Index) and $1 ) then
59087 Mask := $FF;
59088 Result := CF^ and Mask;
59089 end;
59092 //[procedure TControl.RESetFontAttr]
59093 procedure TControl.RESetFontAttr(const Index, Value: Integer);
59094 {const
59095 CFE_MASK = CFE_AUTOCOLOR or CFE_BOLD or CFE_ITALIC or CFE_PROTECTED or CFE_STRIKEOUT or
59096 CFE_UNDERLINE or CFE_LINK or CFE_SUBSCRIPT or CFE_SUPERSCRIPT or}
59097 var CF: PDWORD;
59098 Mask: DWORD;
59099 begin
59100 REGetFont;
59101 CF := Pointer( Integer( @fRECharFormatRec ) + (HiWord(Index) and $7E) );
59102 Mask := 0;
59103 if LongBool( HiWord(Index) and $1 ) then
59104 Mask := $FFFFFF00;
59105 CF^ := CF^ and Mask or DWORD(Value);
59106 fRECharFormatRec.dwMask := Index and $FF81FFFF;
59107 if LongBool( fRECharFormatRec.dwMask and (CFM_COLOR or CFM_BACKCOLOR) ) then
59108 fRECharFormatRec.dwEffects := fRECharFormatRec.dwEffects and
59109 not (CFE_AUTOCOLOR or CFE_AUTOBACKCOLOR);
59110 {fRECharFormatRec.dwEffects := fRECharFormatRec.dwEffects and CFE_MASK;}
59111 Perform( EM_SETCHARFORMAT, RichAreas[ fRECharArea ], Integer( @fRECharFormatRec ) );
59112 end;
59114 //[procedure TControl.RESetFontAttr1]
59115 procedure TControl.RESetFontAttr1(const Index, Value: Integer);
59116 begin
59117 RESetFontAttr( Index, Color2RGB( Value ) );
59118 end;
59121 //[function TControl.REGetFontSizeValid]
59122 function TControl.REGetFontSizeValid: Boolean;
59123 begin
59124 Result := REGetFontMask( Integer( CFM_SIZE ) );
59125 end;
59128 //[function TControl.REGetFontName]
59129 function TControl.REGetFontName: String;
59130 begin
59131 ReGetFont;
59132 Result := fRECharFormatRec.szFaceName;
59133 end;
59136 //[procedure TControl.RESetFontName]
59137 procedure TControl.RESetFontName(const Value: String);
59138 begin
59139 ReGetFont;
59140 StrLCopy( fRECharFormatRec.szFaceName, PChar( Value ), Sizeof( fRECharFormatRec.szFaceName ) - 1 );
59141 fRECharFormatRec.dwMask := CFM_FACE;
59142 Perform( EM_SETCHARFORMAT, RichAreas[ fRECharArea ], Integer( @fRECharFormatRec ) );
59143 end;
59146 //[procedure TControl.SelectAll]
59147 procedure TControl.SelectAll;
59148 begin
59149 SelStart := 0;
59150 SelLength := -1; // this can be not working for some controls... //*//*
59151 end;
59154 //[function TControl.REGetCharformat]
59155 function TControl.REGetCharformat: TCharFormat;
59156 begin
59157 REGetFont;
59158 Result := fRECharFormatRec;
59159 end;
59162 //[procedure TControl.RESetCharFormat]
59163 procedure TControl.RESetCharFormat(const Value: TCharFormat);
59164 begin
59165 Perform( EM_SETCHARFORMAT, RichAreas[ fRECharArea ], Integer( @Value ) );
59166 end;
59169 //[function REOut2Stream]
59170 function REOut2Stream( Sender: PControl; Buf: PByte; Sz: DWORD; pSz: PInteger )
59171 :DWORD; stdcall;
59172 begin
59173 if Sz + Sender.fREStream.Position > Sender.fREStream.Size then
59174 Sender.fREStream.Size := Sender.fREStream.Size + DWORD( {Min(} Sz {, 8192 )} );
59175 pSz^ := Sender.fREStream.Write( Buf^, Sz );
59176 if Assigned( Sender.fOnProgress ) then
59177 Sender.fOnProgress( Sender );
59178 Result := 0;
59179 end;
59181 const TextTypes: array[ TRETextFormat ] of WORD = ( SF_RTF, SF_TEXT,
59182 SF_RTF or SFF_PLAINRTF, SF_RTFNOOBJS, SF_RTFNOOBJS or SFF_PLAINRTF,
59183 SF_TEXTIZED );
59186 //[function TControl.RE_SaveToStream]
59187 function TControl.RE_SaveToStream(Stream: PStream; Format: TRETextFormat;
59188 SelectionOnly: Boolean): Boolean;
59189 var ES: TEditStream;
59190 SelFlag: Integer;
59191 begin
59192 fREStream := Stream;
59193 ES.dwCookie := Integer( @Self );
59194 ES.dwError := 0;
59195 ES.pfnCallback := @REOut2Stream;
59196 SelFlag := 0;
59197 if SelectionOnly then
59198 SelFlag := SFF_SELECTION;
59199 Perform( EM_STREAMOUT, TextTypes[ Format ] or SelFlag, Integer( @ES ) );
59200 fREStream := nil;
59201 fREError := ES.dwError;
59202 Result := fREError = 0;
59203 end;
59205 //[procedure RE_AddText]
59206 procedure RE_AddText( Self_: PControl; const S: String );
59207 begin
59208 Self_.SelStart := Self_.TextSize;
59209 Self_.RE_Text[ reText, True ] := S;
59210 end;
59213 //[function TControl.REReadText]
59214 function TControl.REReadText(Format: TRETextFormat;
59215 SelectionOnly: Boolean): String;
59216 var B0: Integer;
59217 MS: PStream;
59218 begin
59219 fCommandActions.aAddText := RE_AddText;
59220 MS := NewMemoryStream;
59221 RE_SaveToStream( MS, Format, SelectionOnly );
59222 B0 := 0;
59223 MS.Write( B0, 1 );
59224 Result := PChar( MS.fMemory );
59225 MS.Free;
59226 end;
59229 //[function REInFromStream]
59230 function REInFromStream( Sender: PControl; Buf: PByte; Sz: DWORD; pSz: PInteger )
59231 :DWORD; stdcall;
59232 begin
59233 {$IFDEF _D3} if Sender.fREStrLoadLen >= 0 then {$ENDIF}
59234 if Sz > Sender.fREStrLoadLen then
59235 Sz := Sender.fREStrLoadLen;
59236 pSz^ := Sender.fREStream.Read( Buf^, Sz );
59237 Dec( Sender.fREStrLoadLen, pSz^ );
59238 if Assigned( Sender.fOnProgress ) then
59239 Sender.fOnProgress( Sender );
59240 Result := 0;
59241 end;
59244 //[function TControl.RE_LoadFromStream]
59245 function TControl.RE_LoadFromStream(Stream: PStream; Length: Integer;
59246 Format: TRETextFormat; SelectionOnly: Boolean): Boolean;
59247 var ES: TEditStream;
59248 SelFlag: Integer;
59249 begin
59250 fREStream := Stream;
59251 fREStrLoadLen := DWORD( Length );
59252 ES.dwCookie := Integer( @Self );
59253 ES.dwError := 0;
59254 ES.pfnCallback := @REInFromStream;
59255 SelFlag := 0;
59256 if SelectionOnly then
59257 SelFlag := SFF_SELECTION;
59258 Perform( EM_STREAMIN, TextTypes[ Format ] or SelFlag, Integer( @ES ) );
59259 fREStream := nil;
59260 fREError := ES.dwError;
59261 Result := fREError = 0;
59262 end;
59265 //[procedure TControl.REWriteText]
59266 procedure TControl.REWriteText(Format: TRETextFormat;
59267 SelectionOnly: Boolean; const Value: String);
59268 var MS: PStream;
59269 begin
59270 fCommandActions.aAddText := RE_AddText;
59271 MS := NewMemoryStream;
59272 MS.fMemory := PChar( Value );
59273 MS.fData.fSize := Length( Value );
59274 MS.fData.fCapacity := MS.fData.fSize;
59275 RE_LoadFromStream( MS, MS.fData.fSize, Format, SelectionOnly );
59276 MS.fMemory := nil;
59277 MS.Free;
59278 end;
59281 //[function TControl.RE_LoadFromFile]
59282 function TControl.RE_LoadFromFile(const Filename: String;
59283 Format: TRETextFormat; SelectionOnly: Boolean): Boolean;
59284 var Strm: PStream;
59285 begin
59286 Strm := NewReadFileStream( Filename );
59287 Result := RE_LoadFromStream( Strm, -1, Format, SelectionOnly );
59288 Strm.Free;
59289 end;
59292 //[function TControl.RE_SaveToFile]
59293 function TControl.RE_SaveToFile(const Filename: String;
59294 Format: TRETextFormat; SelectionOnly: Boolean): Boolean;
59295 var Strm: PStream;
59296 begin
59297 Strm := NewWriteFileStream( Filename );
59298 Result := RE_SaveToStream( Strm, Format, SelectionOnly );
59299 Strm.Free;
59300 end;
59303 //[function TControl.REGetParaFmt]
59304 function TControl.REGetParaFmt: TParaFormat;
59305 begin
59306 FillChar( Result, sizeof( TParaFormat2 ), 0 );
59307 Result.cbSize := sizeof( RichEdit.TParaFormat ) + fParaFmtDeltaSz;
59308 Perform( EM_GETPARAFORMAT, 0, Integer( @Result ) );
59309 end;
59312 //[procedure TControl.RESetParaFmt]
59313 procedure TControl.RESetParaFmt(const Value: TParaFormat);
59314 begin
59315 //Value.cbSize := szTParaFmtRec;
59316 Perform( EM_SETPARAFORMAT, 0, Integer( @Value ) );
59317 end;
59320 //[function TControl.REGetNumbering]
59321 function TControl.REGetNumbering: Boolean;
59322 begin
59323 Result := LongBool( ReGetParaAttr( 9 shl 16 ) );
59324 end;
59327 //[function TControl.REGetParaAttr]
59328 function TControl.REGetParaAttr( const Index: Integer ): Integer;
59329 var pDw : PDWORD;
59330 begin
59331 fREParaFmtRec := REGetParaFmt;
59332 pDw := Pointer( Integer( @fREParaFmtRec ) + ( HiWord( Index ) and $7E ) );
59333 Result := pDw^;
59334 if LongBool( HiWord( Index ) and 1 ) then
59335 Result := Result and $FFFF;
59336 end;
59339 //[function TControl.REGetParaAttrValid]
59340 function TControl.REGetParaAttrValid( const Index: Integer ): Boolean;
59341 begin
59342 Result := LongBool( ReGetParaAttr( 4 shl 16 ) and Index );
59343 end;
59346 //[function TControl.REGetTabCount]
59347 function TControl.REGetTabCount: Integer;
59348 begin
59349 Result := ReGetParaAttr( 27 shl 16 );
59350 end;
59353 //[function TControl.REGetTabs]
59354 function TControl.REGetTabs(Idx: Integer): Integer;
59355 begin
59356 Result := ReGetParaAttr( (28 + 4 * Idx) shl 16 );
59357 end;
59360 //[function TControl.REGetTextAlign]
59361 function TControl.REGetTextAlign: TRichTextAlign;
59362 begin
59363 Result := TRichTextAlign( ReGetParaAttr( 25 shl 16 ) - 1 );
59364 end;
59367 //[procedure TControl.RESetNumbering]
59368 procedure TControl.RESetNumbering(const Value: Boolean);
59369 begin
59370 RESetParaAttr( (9 shl 16) or PFM_NUMBERING, Integer( Value ) );
59371 end;
59374 //[procedure TControl.RESetParaAttr]
59375 procedure TControl.RESetParaAttr(const Index, Value: Integer);
59376 var pDw: PDWORD;
59377 Mask: Integer;
59378 begin
59379 REGetParaAttr( 0 );
59380 pDw := Pointer( Integer( @fREParaFmtRec ) + ( HiWord( Index ) and $7E ) );
59381 Mask := 0;
59382 if LongBool( HiWord( Index ) and 1 ) then
59383 Mask := Integer( $FFFF0000 );
59384 pDw^ := pDw^ and Mask or DWORD(Value);
59385 //////////////////////////////////////////////////////////////////////////////
59386 fREParaFmtRec.dwMask := Index and $8000FFFF;
59387 //////////////////////////////////////////////////////////////////////////////
59388 //fREParaFmtRec.dwMask := DWORD( Index ) or $8000FFFF; //
59389 //////////////////////////////////////////////////////////////////////////////
59390 RESetParaFmt( fREParaFmtRec );
59391 end;
59394 //[procedure TControl.RESetTabCount]
59395 procedure TControl.RESetTabCount(const Value: Integer);
59396 begin
59397 REGetParaAttr( 0 );
59398 RESetParaAttr( (27 shl 16) or PFM_TABSTOPS, Value );
59399 end;
59402 //[procedure TControl.RESetTabs]
59403 procedure TControl.RESetTabs(Idx: Integer; const Value: Integer);
59404 begin
59405 REGetParaAttr( 0 );
59406 RESetParaAttr( (28 + 4 * Idx) or PFM_TABSTOPS, Value );
59407 end;
59410 //[procedure TControl.RESetTextAlign]
59411 procedure TControl.RESetTextAlign(const Value: TRichTextAlign);
59412 begin
59413 RESetParaAttr( (25 shl 16) or PFM_ALIGNMENT, Ord( Value ) + 1 );
59414 end;
59417 //[function TControl.REGetStartIndentValid]
59418 function TControl.REGetStartIndentValid: Boolean;
59419 begin
59420 Result := REGetParaAttrValid( Integer( PFM_STARTINDENT ) );
59421 end;
59424 //[procedure TControl.RE_HideSelection]
59425 procedure TControl.RE_HideSelection(aHide: Boolean);
59426 begin
59427 Perform( EM_HIDESELECTION, Integer( aHide ), 1 );
59428 end;
59431 //[function TControl.RE_SearchText]
59432 function TControl.RE_SearchText(const Value: String; MatchCase,
59433 WholeWord, ScanForward: Boolean; SearchFrom, SearchTo: Integer): Integer;
59434 var Flags: Integer;
59435 FT: TFindText;
59436 begin
59437 Flags := Integer( ScanForward );
59438 if WholeWord then Flags := Flags or FT_WHOLEWORD;
59439 if MatchCase then Flags := Flags or FT_MATCHCASE;
59440 FT.chrg.cpMin := SearchFrom;
59441 FT.chrg.cpMax := SearchTo;
59442 FT.lpstrText := PChar( Value );
59443 Result := Perform( EM_FINDTEXT, Flags, Integer( @FT ) );
59444 end;
59447 //[function TControl.CanUndo]
59448 function TControl.CanUndo: Boolean;
59449 begin
59450 Result := LongBool( Perform( EM_CANUNDO, 0, 0 ) );
59451 end;
59454 //[procedure TControl.EmptyUndoBuffer]
59455 procedure TControl.EmptyUndoBuffer;
59456 begin
59457 Perform( EM_EMPTYUNDOBUFFER, 0, 0 );
59458 end;
59461 //[function TControl.Undo]
59462 function TControl.Undo: Boolean;
59463 begin
59464 Result := LongBool( Perform( EM_UNDO, 0, 0 ) );
59465 end;
59468 //[function TControl.RE_Redo]
59469 function TControl.RE_Redo: Boolean;
59470 begin
59471 Result := LongBool( Perform( EM_REDO, 0, 0 ) );
59472 end;
59475 //[function TControl.REGetAutoURLDetect]
59476 function TControl.REGetAutoURLDetect: Boolean;
59477 begin
59478 Result := LongBool( Perform( EM_GETAUTOURLDETECT, 0, 0 ) );
59479 end;
59482 //[procedure TControl.RESetAutoURLDetect]
59483 procedure TControl.RESetAutoURLDetect(const Value: Boolean);
59484 begin
59485 AttachProc( WndProc_RE_LinkNotify );
59486 Perform( EM_AUTOURLDETECT, Integer( Value ), 0 );
59487 end;
59490 //[function TControl.GetMaxTextSize]
59491 function TControl.GetMaxTextSize: DWORD;
59492 begin
59493 Result := Perform( EM_GETLIMITTEXT, 0, 0 );
59494 end;
59497 //[procedure TControl.SetMaxTextSize]
59498 procedure TControl.SetMaxTextSize(const Value: DWORD);
59499 var V1, V2: Integer;
59500 begin
59501 if fCommandActions.aSetLimit <> 0 then
59502 begin
59503 V1 := 0; V2 := Value;
59504 if fCommandActions.aSetLimit = EM_SETLIMITTEXT then
59505 begin
59506 V1 := Value; V2 := 0;
59507 end;
59508 Perform( fCommandActions.aSetLimit, V1, V2 );
59509 end;
59510 end;
59513 //[function WndProc_REFmt]
59514 function WndProc_REFmt( _Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
59515 var Mask: Integer;
59516 Shft, Flg: Boolean;
59517 Delta: Integer;
59518 TA: TRichTextAlign;
59519 ChgTA: Boolean;
59520 US: TRichUnderline;
59521 NS: TRichNumbering;
59522 NB: TRichNumBrackets;
59523 Side: TBorderEdge;
59524 Param: DWORD;
59525 begin
59526 Result := False;
59527 if Msg.message = WM_CHAR then
59528 if _Self_.FSupressTab then
59529 begin
59530 _Self_.FSupressTab := FALSE;
59531 if Msg.wParam = 9 then
59532 begin
59533 Result := TRUE;
59534 Exit;
59535 end;
59536 end;
59538 if Msg.message = WM_KEYDOWN then
59539 if GetKeyState( VK_CONTROL ) < 0 then
59540 begin
59541 Shft := GetKeyState( VK_SHIFT ) < 0;
59542 Rslt := 0;
59543 Result := True;
59544 Mask := 0;
59545 ChgTA := False; TA := raLeft;
59546 Param := Msg.wParam;
59547 //Msg.wParam := 0;
59548 case Param of
59549 Integer('Z'):
59550 begin
59551 if Shft then
59552 begin
59553 _Self_.RE_Redo;
59554 Exit;
59555 end;
59556 Result := False;
59557 end;
59559 Integer('L'): begin ChgTA := True; TA := raLeft; end;
59560 Integer('R'): begin ChgTA := True; TA := raRight; end;
59561 Integer('E'): begin ChgTA := True; TA := raCenter; end;
59562 Integer('J'): begin ChgTA := True; TA := raJustify; end;
59563 Integer('N'): begin
59564 if Shft then
59565 begin
59566 NS := _Self_.RE_NumStyle;
59567 NB := _Self_.RE_NumBrackets;
59568 if NS = rnBullets then
59569 begin
59570 _Self_.RE_NumStyle := rnNone;
59571 Exit;
59572 end;
59573 if NS = rnNone then
59574 begin
59575 _Self_.RE_NumStyle := rnBullets;
59576 //NB := rnbPlain;
59577 Exit;
59579 else
59580 if Ord( NB ) = 0 then
59581 NB := High(NB) else
59582 NB := Pred(NB);
59583 _Self_.RE_NumBrackets := NB;
59585 else
59586 begin
59587 NS := _Self_.RE_NumStyle;
59588 if Ord( NS ) = 0 then
59589 begin
59590 NS := rnURoman; //rnULetter; //High( NS );
59591 { because rnLRoman, rnURoman, rnNoNumber are not shown
59592 in RichEdit. }
59593 _Self_.RE_NumBrackets := rnbPeriod;
59594 end else
59595 NS := Pred(NS);
59596 _Self_.RE_NumStyle := NS;
59597 if NS in [ rnLRoman, rnURoman, rnArabic ] then
59598 _Self_.RE_NumStart := 1;
59599 end;
59600 Exit;
59601 end;
59602 Integer('W'): begin
59603 Delta := _Self_.RE_BorderWidth[ beLeft ] + 4;
59604 if Shft then Delta := -1;
59605 for Side := Low(Side) to High(Side) do
59606 begin
59607 if Delta < 0 then
59608 _Self_.RE_BorderStyle[ Side ] := _Self_.RE_BorderStyle[ Side ] + 1
59609 else
59610 begin
59611 _Self_.RE_BorderWidth[ Side ] := Delta;
59612 _Self_.RE_BorderSpace[ Side ] := Delta;
59613 end;
59614 end;
59615 Exit;
59616 end;
59617 (* TABLES STUFF -- to try, uncomment it and press CTRL+T in RichEdit.
59618 (and uncomment declaration for Tmp above).
59620 Not finished, and seems no way to figure it out - even RichEdit20.dll
59621 (i.e. Rich Edit v3.0) can not display tables properly formatted. :(((
59623 Integer('T'): begin
59624 if _Self_.RE_Table then
59625 begin
59626 //MsgOK( 'table' );
59627 end;
59628 Tmp := _Self_.REReadText( reRTF, True );
59629 if StrIsStartingFrom( PChar(Tmp), '{\rtf' )
59630 and (CopyTail( Tmp, 3 ) = '}'#$D#$A) then
59631 begin
59632 //Tmp := Copy( Tmp, 1, Length(Tmp) - 3 );
59633 _Self_.RE_Text[ reRTF, True ] := '{\rtf1' + //Copy( Tmp, 1, 6 ) +
59634 '\trowd' +
59635 //'\lytcalctblwd' +
59636 //'\oldlinewrap' +
59637 //'\alntblind' +
59638 //'\trgaph108' +
59639 '\trleft-108' +
59640 {'\trbrdrt\brdrs\brdrw10' +
59641 '\trbrdrl\brdrs\brdrw10' +
59642 '\trbrdrb\brdrs\brdrw10' +
59643 '\trbrdrr\brdrs\brdrw10' +
59644 '\trbrdrh\brdrs\brdrw10' +
59645 '\trbrdrv\brdrs\brdrw10' +}
59646 //'\clvertalt' +
59647 {'\clbrdrt\brdrs\brdrw10' +
59648 '\clbrdrl\brdrs\brdrw10' +
59649 '\clbrdrb\brdrs\brdrw10' +
59650 '\clbrdrr\brdrs\brdrw10' +}
59651 //'\cltxlrtb' +
59652 '\cellx1414' +
59653 //'\pard' +
59654 //'\plain' +
59655 //'\widctlpar' +
59656 '\trautofit1' +
59657 '\intbl' +
59658 //'\adjustright' +
59659 //'\fs20\lang1049' +
59660 //'\cgrid' +
59661 '\trrh0' +
59662 '{\clFitText{{\box\brdrs\brdrw20\brsp20}'+
59663 '\par}\cell\row}' +
59664 //'\pard\widctlpar' +
59665 //'\intbl'+
59666 //'\adjustright'+
59667 //'{\row}' +
59668 '\pard\widctlpar' +
59669 '}'#$D#$A;
59670 _Self_.Perform( WM_KEYDOWN, VK_UP, 0 );
59671 _Self_.Perform( WM_KEYUP, VK_UP, 0 );
59672 end;
59673 Exit;
59674 end;
59676 Integer('B'): Mask := CFM_BOLD;
59677 Integer('I'):
59678 begin
59679 Mask := CFM_ITALIC;
59680 _Self_.FSupressTab := TRUE;
59681 end;
59682 Integer('U'):
59683 begin
59684 if Shft then
59685 begin
59686 US := _Self_.RE_FmtUnderlineStyle;
59687 if Ord(US) = 0 then US := High(TRichUnderLine)
59688 else US := Pred( US );
59689 _Self_.RE_FmtUnderlineStyle := US;
59690 Exit;
59691 end;
59692 Mask := CFM_UNDERLINE;
59693 end;
59694 Integer('O'): Mask := CFM_STRIKEOUT;
59695 VK_SUBTRACT, VK_ADD: Mask := Integer( CFM_SIZE );
59696 else
59697 begin
59698 Result := False;
59699 Msg.wParam := Param;
59700 end;
59701 end;
59702 if not Result then Exit;
59704 if ChgTA then
59705 begin
59706 if Shft then Result := False
59707 else _Self_.RE_TextAlign := TA;
59708 Exit;
59709 end;
59711 _Self_.REGetFont;
59712 if Mask > 0 then
59713 begin
59714 if Shft then Result := False
59715 else begin
59716 Flg := _Self_.REGetFontEffects( Mask );
59717 if not Flg then
59718 _Self_.fRECharFormatRec.dwEffects := _Self_.fRECharFormatRec.dwEffects and not Mask;
59719 _Self_.fRECharFormatRec.dwEffects := _Self_.fRECharFormatRec.dwEffects xor DWORD(Mask);
59720 end;
59722 else
59723 begin
59724 if Msg.wParam = VK_SUBTRACT then
59725 Delta := -1
59726 else
59727 Delta := 1;
59728 if Shft then
59729 Mask := CFM_OFFSET;
59730 if Shft then
59731 Inc( _Self_.fRECharFormatRec.yOffset, Delta * _Self_.fRECharFormatRec.yHeight div 3 )
59732 else
59733 Inc( _Self_.fRECharFormatRec.yHeight, Delta * _Self_.fRECharFormatRec.yHeight div 8 );
59734 Flg := LongBool( _Self_.fRECharFormatRec.dwMask and Mask );
59735 if not Flg then
59736 _Self_.fRECharFormatRec.yOffset := 0;
59737 end;
59738 _Self_.fRECharFormatRec.dwMask := Mask;
59739 _Self_.Perform( EM_SETCHARFORMAT, SCF_SELECTION { RichAreas[ _Self_.fRECharArea ] }, Integer( @_Self_.fRECharFormatRec ) );
59740 end;
59741 end;
59744 //[function TControl.RE_FmtStandard]
59745 function TControl.RE_FmtStandard: PControl;
59746 begin
59747 AttachProc( WndProc_REFmt );
59748 Result := @Self;
59749 end;
59751 //[FUNCTION EnumDynHandlers]
59752 {$IFDEF ASM_VERSION}
59753 function EnumDynHandlers( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
59754 asm //cmd //opd
59755 CMP [EAX].TControl.fRefCount, 0
59756 JL @@fin_false
59757 PUSHAD
59758 MOV EBX, EAX
59759 MOV EBP, ECX
59760 MOV ECX, [EBX].TControl.fDynHandlers
59761 JECXZ @@ret_false
59762 MOV ESI, ECX
59763 MOV ECX, [ESI].TList.fCount
59764 JECXZ @@ret_false
59765 MOV EDI, ECX
59766 SHR EDI, 1
59767 CALL TControl.RefInc
59768 @@loo: DEC EDI
59769 JS @@e_loo
59770 PUSH EDX
59771 PUSH EBX
59772 {$IFNDEF ENUM_DYN_HANDLERS_AFTER_RUN}
59773 XOR EAX, EAX
59774 CMP [AppletTerminated], AL
59775 JZ @@do_call
59776 MOV ECX, [ESI].TList.fItems
59777 MOV ECX, [ECX+EDI*8+4]
59778 JECXZ @@skip_call
59779 {$ENDIF}
59780 @@do_call:
59781 MOV EAX, [ESI].TList.fItems
59782 MOV EAX, [EAX+EDI*8]
59783 XCHG EAX, EBX
59784 MOV ECX, EBP
59785 CALL EBX
59786 @@skip_call:
59787 POP EBX
59788 POP EDX
59789 TEST AL, AL
59790 JZ @@loo
59791 @@ret_true:
59792 MOV EAX, EBX
59793 CALL TControl.RefDec
59794 POPAD
59795 MOV AL, 1
59797 @@e_loo:
59798 XOR EAX, EAX
59799 INC EAX
59800 CMP [EBX].TControl.fRefCount, EAX
59801 JE @@ret_true
59802 MOV EAX, EBX
59803 CALL TControl.RefDec
59804 @@ret_false:
59805 POPAD
59806 @@fin_false:
59807 XOR EAX, EAX
59808 end;
59809 {$ELSE ASM_VERSION} //Pascal
59810 function EnumDynHandlers( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
59811 var I: Integer;
59812 Proc: TWindowFunc;
59813 begin
59814 Result := False;
59815 if Self_.fRefCount < 0 then Exit;
59816 if (Self_.fDynHandlers = nil) or (Self_.fDynHandlers.fCount = 0) then Exit;
59817 Self_.RefInc; // Prevent destroying Self_
59818 for I := Self_.fDynHandlers.fCount div 2 - 1 downto 0 do
59819 begin
59820 Proc := Self_.fDynHandlers.fItems[ I * 2 ];
59821 {$IFNDEF ENUM_DYN_HANDLERS_AFTER_RUN}
59822 if not AppletTerminated or (Self_.fDynHandlers.fItems[ I * 2 + 1 ] <> nil) then
59823 {$ENDIF}
59824 if Proc( Self_, Msg, Rslt ) then
59825 begin
59826 Result := True;
59827 break;
59828 end;
59829 end;
59830 {$IFDEF DEBUG_ENDSESSION}
59831 if EndSession_Initiated then
59832 begin
59833 LogFileOutput( GetStartDir + 'es_debug.txt',
59834 'ENUM_DYN_HANDLERS: Self_:' + Int2Hex( DWORD( Self_ ), 8 ) );
59835 LogFileOutput( GetStartDir + 'es_debug.txt',
59836 'ENUM_DYN_HANDLERS: Self_.fRefCount:' + Int2Str( Self_.fRefCount ) );
59837 end;
59838 {$ENDIF}
59839 if LongBool(Self_.fRefCount and 1) then
59840 Result := True; // If Self_ will be destroyed now, stop further processing
59841 Self_.RefDec; // Destroy Self_, if Free was called for it while processing attached procedures
59842 end;
59843 {$ENDIF ASM_VERSION}
59844 //[END EnumDynHandlers]
59846 {$IFDEF ASM_VERSION}
59847 //[procedure TControl.AttachProcEx]
59848 procedure TControl.AttachProcEx( Proc: TWindowFunc; ExecuteAfterAppletTerminated: Boolean );
59849 asm //cmd //opd
59850 PUSH EBX
59851 PUSH EDI
59852 PUSH ECX
59853 XCHG EBX, EAX
59854 MOV EDI, EDX
59855 MOV [EBX].fOnDynHandlers, offset[EnumDynHandlers]
59856 MOV ECX, [EBX].TControl.fDynHandlers
59857 INC ECX
59858 LOOP @@1
59859 CALL NewList
59860 XCHG ECX, EAX
59861 MOV [EBX].TControl.fDynHandlers, ECX
59862 @@1:
59863 PUSH ECX
59864 MOV EAX, EBX
59865 MOV EDX, EDI
59866 CALL TControl.IsProcAttached
59867 TEST AL, AL
59868 POP EBX
59869 JNZ @@exit
59870 MOV EAX, EBX
59871 MOV EDX, EDI
59872 CALL TList.Add
59873 XCHG EAX, EBX
59874 POP EDX
59875 PUSH EDX
59876 CALL TList.Add
59877 @@exit:
59878 POP ECX
59879 POP EDI
59880 POP EBX
59881 end;
59882 {$ELSE ASM_VERSION} //Pascal
59883 procedure TControl.AttachProcEx( Proc: TWindowFunc; ExecuteAfterAppletTerminated: Boolean );
59884 begin
59885 if fDynHandlers = nil then
59886 fDynHandlers := NewList;
59887 if not IsProcAttached( Proc ) then
59888 begin
59889 fDynHandlers.Add( @Proc );
59890 fDynHandlers.Add( Pointer( Integer( ExecuteAfterAppletTerminated ) ) );
59891 end;
59892 fOnDynHandlers := EnumDynHandlers;
59893 end;
59894 {$ENDIF ASM_VERSION}
59896 //[procedure TControl.AttachProc]
59897 procedure TControl.AttachProc(Proc: TWindowFunc);
59898 begin
59899 AttachProcEx( Proc, FALSE );
59900 end;
59903 //[procedure TControl.DetachProc]
59904 procedure TControl.DetachProc(Proc: TWindowFunc);
59905 var I: Integer;
59906 begin
59907 if fDynHandlers = nil then Exit;
59908 I := fDynHandlers.IndexOf( @Proc );
59909 if I >=0 then
59910 begin
59911 fDynHandlers.Delete( I );
59912 fDynHandlers.Delete( I );
59913 end;
59914 end;
59916 {$IFDEF ASM_VERSION}
59917 //[function TControl.IsProcAttached]
59918 function TControl.IsProcAttached(Proc: TWindowFunc): Boolean;
59919 asm //cmd //opd
59920 MOV ECX, [EAX].TControl.fDynHandlers
59921 JECXZ @@exit
59922 XCHG EAX, ECX
59923 CALL TList.IndexOf
59924 TEST EAX, EAX
59925 SETGE CL
59926 @@exit: XCHG EAX, ECX
59927 end;
59928 {$ELSE ASM_VERSION} //Pascal
59929 function TControl.IsProcAttached(Proc: TWindowFunc): Boolean;
59930 var I: Integer;
59931 begin
59932 Result := False;
59933 if fDynHandlers = nil then Exit;
59934 I := fDynHandlers.IndexOf( @Proc );
59935 Result := I >=0;
59936 end;
59937 {$ENDIF ASM_VERSION}
59939 //[function WndProcAutoPopupMenu]
59940 function WndProcAutoPopupMenu( Control: PControl; var Msg: TMsg; var MsgRslt: Integer ): Boolean;
59941 var R: TRect;
59942 M: Word;
59943 I: Integer;
59944 P: TPoint;
59945 begin
59946 if (Msg.message = WM_CONTEXTMENU) and
59947 (Control.fAutoPopupMenu <> nil) then
59948 begin
59949 {$IFDEF USE_MENU_CURCTL}
59950 PMenu( Control.fAutoPopupMenu ).fCurCtl := Control;
59951 {$ENDIF USE_MENU_CURCTL}
59952 P.X := SmallInt( LoWord( Msg.lParam ) );
59953 P.Y := SmallInt( HiWord( Msg.lParam ) );
59954 if (Msg.lParam = -1) then
59955 begin
59956 I := Control.CurIndex;
59957 M := Control.fCommandActions.aItem2XY;
59958 if (I >= 0) and (M <> 0) then
59959 begin
59960 CASE M OF
59961 EM_POSFROMCHAR:
59962 begin
59963 I := Control.SelStart + Control.SelLength;
59964 // Edit or Rich Edit 2:
59965 I := Control.Perform( M, I, 1 );
59966 P.X := SmallInt( LoWord( I ) );
59967 P.Y := SmallInt( HiWord( I ) );
59968 end;
59969 LB_GETITEMRECT, LVM_GETITEMRECT, TCM_GETITEMRECT:
59970 begin
59971 R.Left := LVIR_BOUNDS;
59972 Control.Perform( M, I, Integer( @ R ) );
59973 P.X := R.Left;
59974 P.Y := R.Bottom;
59975 end;
59976 TVM_GETITEMRECT:
59977 begin
59978 I := Control.TVSelected;
59979 R.Left := I;
59980 Control.Perform( M, 1, Integer( @ R ) );
59981 P.X := R.Left;
59982 P.Y := R.Bottom;
59983 end;
59984 END;
59985 R := Control.ClientRect;
59986 if P.X < R.Left then P.X := R.Left;
59987 if P.X > R.Right then P.X := R.Right;
59988 if P.Y < R.Top then P.Y := R.Top;
59989 if P.Y > R.Bottom then P.Y := R.Bottom;
59990 end;
59991 P := Control.Client2Screen( P );
59992 end;
59993 PMenu( Control.fAutoPopupMenu ).Popup( P.X, P.Y );
59994 Result := TRUE;
59996 else
59997 Result := FALSE;
59998 end;
60000 //[procedure TControl.SetAutoPopupMenu]
60001 procedure TControl.SetAutoPopupMenu(PopupMenu: PObj);
60002 { new version - by Alexander Pravdin. Allows to attach a submenu (e.g. of the
60003 main menu) as a popup menu to a control, to avoid duplicating menu object,
60004 if it is the same already as desired. }
60005 var pm: PMenu;
60006 begin
60007 if PopupMenu <> nil then
60008 {$IFDEF USE_MENU_CURCTL}
60009 begin
60010 pm := PMenu( PopupMenu );
60011 if ( pm.FParent <> nil ) then
60012 begin
60013 while pm.FControl = nil do
60014 pm := pm.FParent;
60015 PMenu( PopupMenu ).FControl := pm.FControl;
60017 else
60018 begin
60019 PMenu( PopupMenu ).FControl := @Self;
60020 end;
60021 AttachProc(WndProcAutoPopupMenu);
60022 AttachProc(WndProcMenu)
60024 else begin
60025 DetachProc(WndProcAutoPopupMenu);
60026 DetachProc(WndProcMenu);
60027 end;
60028 {$ELSE}
60029 begin
60030 pm := PMenu( PopupMenu );
60031 while pm.FControl = nil do pm := pm.Parent;
60032 PMenu( PopupMenu ).FControl := pm.FControl;
60033 end;
60034 {$ENDIF}
60035 fAutoPopupMenu := PopupMenu;
60036 {$IFNDEF USE_MENU_CURCTL}
60037 AttachProc( WndProcAutoPopupMenu );
60038 {$ENDIF}
60039 end;
60041 //[function SearchAnsiMnemonics]
60042 function SearchAnsiMnemonics( const S: String ): String;
60043 var I: Integer;
60044 Sh: ShortInt;
60045 begin
60046 Result := S;
60047 for I := 1 to Length( Result ) do
60048 begin
60049 Sh := VkKeyScanEx( Result[ I ], MnemonicsLocale );
60050 if Sh <> -1 then
60051 Result[ I ] := Char( Sh );
60052 end;
60053 end;
60055 //[procedure SupportAnsiMnemonics]
60056 procedure SupportAnsiMnemonics( LocaleID: Integer );
60057 begin
60058 MnemonicsLocale := LocaleID;
60059 SearchMnemonics := SearchAnsiMnemonics;
60060 end;
60062 //[function WndProcMnemonics]
60063 function WndProcMnemonics( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
60064 var Form: PControl;
60066 function HandleMnenonic( Prnt: PControl ): Boolean;
60067 var C: PControl;
60068 XY: Integer;
60069 procedure DoPressMnemonic;
60070 begin
60071 if Msg.message = WM_SYSKEYDOWN then
60072 begin
60073 Form.FPressedMnemonic := Msg.wParam;
60074 C.Perform( WM_LBUTTONDOWN, MK_LBUTTON, XY );
60076 else
60077 begin
60078 Form.FPressedMnemonic := 0;
60079 C.Perform( WM_LBUTTONUP, MK_LBUTTON, XY );
60080 end;
60081 end;
60082 var I, J: Integer;
60083 R: TRect;
60084 begin
60085 for I := 0 to Prnt.ChildCount-1 do
60086 begin
60087 C := Prnt.Children[ I ];
60088 if C.IsButton then
60089 if C.Enabled then
60090 begin
60091 if C.fCommandActions.aGetCount = TB_BUTTONCOUNT then
60092 for J := 0 to C.Count-1 do
60093 begin
60094 if C.TBButtonEnabled[ J ] then
60095 if pos( '&' + Char( Msg.wParam ), SearchMnemonics( C.TBButtonText[ J ] ) ) > 0 then
60096 begin
60097 C.fCurIndex := J;
60098 C.fCurItem := C.TBIndex2Item( J );
60099 R := C.TBButtonRect[ J ];
60100 XY := R.Left or (R.Top shl 16);
60101 DoPressMnemonic;
60102 Result := TRUE;
60103 Exit;
60104 end;
60105 end;
60106 if pos( '&' + Char( Msg.wParam ), SearchMnemonics( C.Caption ) ) > 0 then
60107 begin
60108 XY := 0;
60109 DoPressMnemonic;
60110 Result := TRUE;
60111 Exit;
60112 end;
60113 end;
60114 if HandleMnenonic( C ) then
60115 begin
60116 Result := TRUE;
60117 Exit;
60118 end;
60119 end;
60120 Result := FALSE;
60121 end;
60123 {$IFDEF NEW_MENU_ACCELL}
60124 function FindByCtlRef(C: PControl; Accell: TMenuAccelerator): Boolean;
60126 function FindInMenu(M: PMenu): PMenu;
60128 I: Integer;
60129 SM: PMenu;
60130 begin
60131 for I := 0 to M.FItems.Count - 1 do begin
60132 Result := M.FItems.Items[I];
60133 if (Cardinal(Result.Accelerator) = Cardinal(Accell)) and Result.Enabled then
60134 Exit;
60135 end;
60136 Result := nil;
60137 for I := 0 to M.FItems.Count - 1 do begin
60138 SM := PMenu(M.FItems.Items[I]);
60139 if (SM.FItems.Count > 0) then
60140 Result := FindInMenu(SM);
60141 if (Result <> nil) then
60142 Break;
60143 end;
60144 end;
60146 function FindInMenu2(M: PMenu): Boolean;
60148 MI: PMenu;
60149 begin
60150 if (M <> nil) then begin
60151 MI := FindInMenu(M);
60152 if (MI <> nil) then begin
60153 //M.FControl.Perform(WM_COMMAND, MI.FId, 0);
60154 C.Perform(WM_COMMAND, MI.FId, 0); // fixed
60155 Result := True;
60156 Exit;
60157 end;
60158 end;
60159 Result := False;
60160 end;
60163 Parent: PControl;
60164 begin
60165 Result := False;
60166 if not FindInMenu2(PMenu(C.fAutoPopupMenu)) then
60167 if not FindInMenu2(PMenu(C.fMenuObj)) then begin
60168 Parent := C.Parent;
60169 if (Parent <> nil) then
60170 Result := FindByCtlRef(Parent, Accell);
60171 end;
60172 end;
60175 Ac: TMenuAccelerator;
60176 {$ENDIF}
60177 begin
60178 Result := FALSE;
60179 if (Msg.message >= WM_KEYFIRST) and (Msg.message <= WM_KEYLAST) then
60180 begin
60181 {$IFDEF NEW_MENU_ACCELL}
60182 Ac := MakeAccelerator(FVIRTKEY or GetShiftState, Msg.wParam);
60183 Result := FindByCtlRef(Sender, Ac);
60184 {$ELSE}
60185 if Sender.fAccelTable <> 0 then
60186 Result := LongBool( TranslateAccelerator( Sender.fHandle, Sender.fAccelTable, Msg ) );
60187 if not Result then
60188 begin
60189 if Sender.fCurrentControl <> nil then
60190 if Sender.fCurrentControl.fAccelTable <> 0 then
60191 Result := LongBool( TranslateAccelerator( Sender.fCurrentControl.fHandle,
60192 Sender.fCurrentControl.fAccelTable, Msg ) );
60193 end;
60194 if not Result then
60195 begin
60196 Form := Sender.ParentForm;
60197 if Form <> nil then
60198 if Form.fAccelTable <> 0 then
60199 Result := LongBool( TranslateAccelerator( Form.fHandle,
60200 Form.fAccelTable, Msg ) );
60201 end;
60202 {$ENDIF}
60203 end;
60204 if Result then Exit;
60205 if (Msg.message = WM_SYSKEYUP) or
60206 (Msg.message = WM_SYSKEYDOWN) and (GetKeyState( VK_MENU ) < 0) then
60207 begin
60208 Rslt := 0;
60209 Form := Sender.ParentForm;
60210 if Form <> nil then
60211 begin
60212 { ----------------------- }
60213 //Form.Caption := Form.Caption + '<';
60214 if Char( Msg.wParam ) in [ 'A'..'Z', '0'..'9' ] then
60215 begin
60216 if HandleMnenonic( Form ) then
60217 begin
60218 Result := TRUE;
60219 Exit;
60221 else
60222 begin
60223 { ---------------------- }
60224 //Form.Caption := Form.Caption + '?';
60225 end;
60226 end;
60227 end;
60229 else
60230 if Msg.message = WM_KEYUP then
60231 begin
60232 Rslt := 0;
60233 Form := Sender.ParentForm;
60234 if Form <> nil then
60235 begin
60236 { ------------------------ }
60237 //Form.Caption := Form.Caption + '>';
60238 if Msg.wParam = VK_MENU then
60239 begin
60240 if Form.FPressedMnemonic <> 0 then
60241 Form.FPressedMnemonic := Form.FPressedMnemonic or $80000000;
60243 else
60244 if Char( Msg.wParam ) in [ 'A'..'Z', '0'..'9' ] then
60245 begin
60246 if HandleMnenonic( Form ) then
60247 begin
60248 Result := TRUE;
60249 Exit;
60251 else
60252 begin
60253 { --------------------- }
60254 //Form.Caption := form.Caption + '-';
60255 end;
60256 end;
60257 end;
60258 end;
60259 Result := FALSE;
60260 end;
60262 //[function TControl.SupportMnemonics]
60263 function TControl.SupportMnemonics: PControl;
60264 begin
60265 fGlobalProcKeybd := WndProcMnemonics;
60266 Result := @Self;
60267 end;
60270 //[API RevokeDragDrop]
60271 function RevokeDragDrop(wnd: HWnd): HResult; stdcall;
60272 external 'ole32.dll' name 'RevokeDragDrop';
60275 //[function TControl.RE_NoOLEDragDrop]
60276 function TControl.RE_NoOLEDragDrop: PControl;
60277 begin
60278 RevokeDragDrop( Handle );
60279 Result := @Self;
60280 end;
60283 //[function WndProcOnResize]
60284 function WndProcOnResize( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
60285 begin
60286 if Msg.message = WM_SIZE then
60287 begin
60288 if Assigned( Self_.fOnResize ) then
60289 Self_.fOnResize( Self_ );
60290 end;
60291 Result := False;
60292 end;
60295 //[procedure TControl.SetOnResize]
60296 procedure TControl.SetOnResize(const Value: TOnEvent);
60297 begin
60298 FOnResize := Value;
60299 AttachProc( WndProcOnResize );
60300 end;
60302 //[function WndProcMove]
60303 function WndProcMove( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
60304 begin
60305 if Msg.message = WM_MOVE then
60306 begin
60307 if Assigned( Self_.FOnMove ) then
60308 Self_.FOnMove( Self_ );
60309 end;
60310 Result := False;
60311 end;
60313 //[procedure TControl.SetOnMove]
60314 procedure TControl.SetOnMove(const Value: TOnEvent);
60315 begin
60316 FOnMove := Value;
60317 AttachProc( WndProcMove );
60318 end;
60320 //[function WndProc_REBottomless]
60321 function WndProc_REBottomless( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
60322 begin
60323 if Msg.message = WM_SIZE then
60324 Self_.Perform( EM_REQUESTRESIZE, 0, 0 );
60325 Result := False;
60326 end;
60329 //[function TControl.RE_Bottomless]
60330 function TControl.RE_Bottomless: PControl;
60331 begin
60332 AttachProc( WndProc_REBottomless );
60333 Result := @Self;
60334 end;
60337 //[procedure TControl.RE_Append]
60338 procedure TControl.RE_Append(const S: String; ACanUndo: Boolean);
60339 begin
60340 SelStart := TextSize;
60341 if S <> '' then
60342 begin
60343 ReplaceSelection( S, ACanUndo );
60344 SelStart := TextSize;
60345 end;
60346 end;
60349 //[procedure TControl.RE_InsertRTF]
60350 procedure TControl.RE_InsertRTF(const S: String);
60351 var MS: PStream;
60352 begin
60353 MS := NewMemoryStream;
60354 MS.Size := Length( S ) + 1;
60355 Move( S[ 1 ], MS.Memory^, Length( S ) + 1 );
60356 RE_LoadFromStream( MS, Length( S ), reRTF, TRUE );
60357 MS.Free;
60358 end;
60361 //[procedure TControl.DoSelChange]
60362 procedure TControl.DoSelChange;
60363 begin
60364 if Assigned( fOnSelChange ) then fOnSelChange( @Self )
60365 else
60366 if Assigned( fOnChange ) then fOnChange( @Self );
60367 end;
60370 //[function TControl.REGetUnderlineEx]
60371 function TControl.REGetUnderlineEx: TRichUnderline;
60372 begin
60373 Result := TRichUnderline( REGetFontAttr( (81 shl 16) or CFM_UNDERLINETYPE ) - 1 );
60374 end;
60377 //[procedure TControl.RESetUnderlineEx]
60378 procedure TControl.RESetUnderlineEx(const Value: TRichUnderline);
60379 begin
60380 RESetFontAttr( (81 shl 16) or CFM_UNDERLINETYPE, Ord( Value ) + 1 );
60381 RESetFontEffect( CFM_UNDERLINE, True );
60382 end;
60385 //[function TControl.GetTextSize]
60386 function TControl.GetTextSize: Integer;
60387 begin
60388 Result := 0;
60389 if fHandle <> 0 then
60390 Result := GetWindowTextLength( fHandle );
60391 end;
60394 //[function TControl.REGetTextSize]
60395 function TControl.REGetTextSize(Units: TRichTextSize): Integer;
60396 const TextLengthFlags: array[ TRichTextSizes ] of Integer =
60397 ( not GTL_UseCRLF, not GTL_Precise, GTL_Close, GTL_NUMBytes );
60398 var GTL: TGetTextLengthEx;
60399 begin
60400 GTL.flags := MakeFlags( @Units, TextLengthFlags );
60401 if not(rtsBytes in Units) then
60402 GTL.flags := GTL.flags or GTL_NUMCHARS;
60403 GTL.codepage := CP_ACP;
60404 Result := Perform( EM_GETTEXTLENGTHEX, Integer( @GTL ), 0 );
60405 end;
60407 //[function TControl.RE_TextSizePrecise]
60408 function TControl.RE_TextSizePrecise: Integer;
60409 var gtlex : TGetTextLengthEx;
60410 begin
60411 gtlex.flags := GTL_PRECISE;
60412 gtlex.codepage := CP_ACP;
60413 Result := Perform(EM_GETTEXTLENGTHEX,WPARAM(@gtlex), 0 );
60414 end;
60417 //[function TControl.REGetNumStyle]
60418 function TControl.REGetNumStyle: TRichNumbering;
60419 begin
60420 Result := TRichNumbering( ReGetParaAttr( 9 shl 16 ) );
60421 end;
60424 //[procedure TControl.RESetNumStyle]
60425 procedure TControl.RESetNumStyle(const Value: TRichNumbering);
60426 begin
60427 RESetParaAttr( (9 shl 16) or PFM_NUMBERING, Ord( Value ) );
60428 end;
60431 //[function TControl.REGetNumBrackets]
60432 function TControl.REGetNumBrackets: TRichNumBrackets;
60433 begin
60434 REGetParaAttr( 0 );
60435 Result := TRichNumBrackets( (fREParaFmtRec.wNumberingStyle shr 8) {and 3} );
60436 end;
60439 //[procedure TControl.RESetNumBrackets]
60440 procedure TControl.RESetNumBrackets(const Value: TRichNumBrackets);
60441 begin
60442 REGetParaAttr( 0 );
60443 fREParaFmtRec.wNumberingStyle := fREParaFmtRec.wNumberingStyle and $F8FF
60444 or Word( Ord( Value ) shl 8 );
60445 fREParaFmtRec.dwMask := PFM_NUMBERINGSTYLE;
60446 RE_ParaFmt := fREParaFmtRec;
60447 end;
60450 //[function TControl.REGetNumTab]
60451 function TControl.REGetNumTab: Integer;
60452 begin
60453 REGetParaAttr( 0 );
60454 Result := fREParaFmtRec.wNumberingTab;
60455 end;
60458 //[procedure TControl.RESetNumTab]
60459 procedure TControl.RESetNumTab(const Value: Integer);
60460 begin
60461 REGetParaAttr( 0 );
60462 fREParaFmtRec.wNumberingTab := Value;
60463 fREParaFmtRec.dwMask := PFM_NUMBERINGTAB;
60464 RE_ParaFmt := fREParaFmtRec;
60465 end;
60468 //[function TControl.REGetNumStart]
60469 function TControl.REGetNumStart: Integer;
60470 begin
60471 REGetParaAttr( 0 );
60472 Result := fREParaFmtRec.wNumberingStart;
60473 end;
60476 //[procedure TControl.RESetNumStart]
60477 procedure TControl.RESetNumStart(const Value: Integer);
60478 begin
60479 REGetParaAttr( 0 );
60480 fREParaFmtRec.wNumberingStart := Value;
60481 fREParaFmtRec.dwMask := PFM_NUMBERINGSTART;
60482 RE_ParaFmt := fREParaFmtRec;
60483 end;
60486 //[function TControl.REGetSpacing]
60487 function TControl.REGetSpacing( const Index: Integer ): Integer;
60488 begin
60489 REGetParaAttr( 0 );
60490 Result := PInteger( Integer(@fREParaFmtRec.dySpaceBefore) + (Index and $F) )^;
60491 end;
60494 //[procedure TControl.RESetSpacing]
60495 procedure TControl.RESetSpacing(const Index, Value: Integer);
60496 begin
60497 REGetParaAttr( 0 );
60498 PInteger( Integer(@fREParaFmtRec.dySpaceBefore) + (Index and $F) )^ := Value;
60499 fREParaFmtRec.dwMask := Index and not $F;
60500 RE_ParaFmt := fREParaFmtRec;
60501 end;
60504 //[function TControl.REGetSpacingRule]
60505 function TControl.REGetSpacingRule: Integer;
60506 begin
60507 REGetParaAttr( 0 );
60508 Result := fREParaFmtRec.bLineSpacingRule;
60509 end;
60512 //[procedure TControl.RESetSpacingRule]
60513 procedure TControl.RESetSpacingRule(const Value: Integer);
60514 begin
60515 REGetParaAttr( 0 );
60516 fREParaFmtRec.bLineSpacingRule := Value;
60517 fREParaFmtRec.dwMask := PFM_LINESPACING;
60518 RE_ParaFmt := fREParaFmtRec;
60519 end;
60522 //[function TControl.REGetLevel]
60523 function TControl.REGetLevel: Integer;
60524 begin
60525 REGetParaAttr( 0 );
60526 Result := fREParaFmtRec.bCRC;
60527 end;
60530 //[function TControl.REGetBorder]
60531 function TControl.REGetBorder(Side: TBorderEdge; const Index: Integer): Integer;
60532 begin
60533 REGetParaAttr( 0 );
60534 Result := PWORD( Integer(@fREParaFmtRec.wBorderSpace) + Index )^ shr (Ord(Side) * 4);
60535 end;
60538 //[procedure TControl.RESetBorder]
60539 procedure TControl.RESetBorder(Side: TBorderEdge; const Index: Integer;
60540 const Value: Integer);
60541 var Mask: Word;
60542 pW : PWord;
60543 begin
60544 REGetParaAttr( 0 );
60545 pw := PWORD( Integer(@fREParaFmtRec.wBorderSpace) + Index );
60546 Mask := $F shl (Ord(Side) * 4);
60547 pw^ := pw^ and not Mask or (Value shl (4 * Ord(Side)) );
60548 fREParaFmtRec.dwMask := PFM_BORDER;
60549 RE_ParaFmt := fREParaFmtRec;
60550 end;
60553 //[function TControl.REGetParaEffect]
60554 function TControl.REGetParaEffect(const Index: Integer): Boolean;
60555 begin
60556 Result := LongBool( HiWord( REGetParaAttr( 8 shl 16 ) ) and Index );
60557 end;
60560 //[procedure TControl.RESetParaEffect]
60561 procedure TControl.RESetParaEffect(const Index: Integer;
60562 const Value: Boolean);
60563 var Idx: Integer;
60564 begin
60565 REGetParaAttr( 0 );
60566 fREParaFmtRec.wReserved := Index;
60567 Idx := Index;
60568 //if Idx >= $4000 then Idx := $4000;
60569 fREParaFmtRec.dwMask := Idx shl 16;
60570 RE_ParaFmt := fREParaFmtRec;
60571 end;
60574 //[function WndProc_REMonitorIns]
60575 function WndProc_REMonitorIns( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
60576 begin
60577 Result := False;
60578 if (Msg.message = WM_KEYDOWN) and (Msg.wParam = VK_INSERT) and
60579 ((GetKeyState(VK_CONTROL) or GetKeyState(VK_SHIFT) or GetKeyState(VK_MENU)) >= 0) then
60580 begin
60581 if not Self_.fReOvrDisable then
60582 Self_.fREOvr := not Self_.fREOvr
60583 else
60584 Result := True;
60585 if assigned( Self_.fOnREInsModeChg ) then
60586 Self_.fOnREInsModeChg( Self_ );
60587 end;
60588 end;
60591 //[function TControl.REGetOverwite]
60592 function TControl.REGetOverwite: Boolean;
60593 begin
60594 AttachProc( WndProc_REMonitorIns );
60595 Result := fREOvr;
60596 end;
60599 //[procedure TControl.RESetOverwrite]
60600 procedure TControl.RESetOverwrite(const Value: Boolean);
60601 begin
60602 if fREOvr = Value then Exit;
60603 Perform( WM_KEYDOWN, VK_INSERT, 0 );
60604 Perform( WM_KEYUP, VK_INSERT, 0 );
60605 end;
60608 //[procedure TControl.RESetOvrDisable]
60609 procedure TControl.RESetOvrDisable(const Value: Boolean);
60610 begin
60611 REGetOverwite;
60612 fReOvrDisable := Value;
60613 end;
60616 //[function WndProc_RichEdTransp_ParentPaint]
60617 function WndProc_RichEdTransp_ParentPaint( Self_:PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
60618 var I: Integer;
60619 C: PControl;
60620 begin
60621 if (Msg.message = WM_PAINT) and (Msg.wParam = 0) then
60622 begin
60623 for I := 0 to Self_.fChildren.fCount - 1 do
60624 begin
60625 C := Self_.fChildren.fItems[ I ];
60626 if C.fIsCommonControl then
60627 begin
60628 Inc( C.fUpdCount );
60629 PostMessage( C.fHandle, CM_NCUPDATE, C.fUpdCount, WM_PAINT );
60630 InvalidateRect( C.fHandle, nil, False );
60631 end;
60632 end;
60633 end;
60634 Result := False;
60635 end;
60638 //[function WndProc_RichEdTransp_Update]
60639 function WndProc_RichEdTransp_Update( Self_:PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
60640 var Rgn, Rgn1: HRgn;
60641 R, CR: TRect;
60642 Pt: TPoint;
60643 VW, HH, VH, HW: Integer;
60644 begin
60645 case Msg.message of
60646 WM_CHAR, WM_KILLFOCUS, WM_SETFOCUS:
60647 begin
60648 PostMessage( Self_.fHandle, CM_INVALIDATE, 0, 0 );
60649 end;
60650 WM_PAINT:
60651 if Msg.wParam = 0 then
60652 begin
60653 Inc( Self_.fUpdCount );
60654 PostMessage( Self_.fHandle, CM_NCUPDATE, Self_.fUpdCount, Msg.message );
60655 end;
60656 WM_SIZE:
60657 begin
60658 Inc( Self_.fUpdCount );
60659 PostMessage( Self_.fHandle, CM_NCUPDATE, Self_.fUpdCount, Msg.message );
60660 PostMessage( Self_.fHandle, CM_INVALIDATE, 0, 0 );
60661 end;
60662 WM_ERASEBKGND:
60663 if Msg.wParam = 0 then
60664 begin
60665 Inc( Self_.fUpdCount );
60666 PostMessage( Self_.fHandle, CM_NCUPDATE, Self_.fUpdCount, Msg.message );
60667 end;
60668 WM_HSCROLL, WM_VSCROLL:
60669 begin
60670 Self_.fREScrolling := LoWord( Msg.wParam ) <> SB_ENDSCROLL;
60671 Inc( Self_.fUpdCount );
60672 PostMessage( Self_.fHandle, CM_NCUPDATE, Self_.fUpdCount, Msg.message );
60673 if Self_.fREScrolling then
60674 Self_.Invalidate;
60675 end;
60676 CM_INVALIDATE:
60677 begin
60678 //Self_.Update;
60679 Self_.Parent.Invalidate;
60680 Self_.Invalidate;
60681 //Inc( Self_.fUpdCount );
60682 //PostMessage( Self_.fHandle, CM_NCUPDATE, Self_.fUpdCount, Msg.message );
60683 end;
60684 CM_NCUPDATE:
60685 if Msg.wParam = Self_.fUpdCount then
60686 begin
60687 //if Msg.lParam = WM_PAINT then
60688 // UpdateWindow( Self_.fHandle );
60689 GetWindowRect( Self_.fHandle, R );
60690 Windows.GetClientRect( Self_.fHandle, CR );
60691 Pt.x := 0; Pt.y := 0;
60692 Pt := Self_.Client2Screen( Pt );
60693 OffsetRect( CR, Pt.x, Pt.y );
60694 Rgn := CreateRectRgn( R.Left, R.Top, R.Right, R.Bottom );
60695 if Self_.fREScrolling then
60696 begin
60697 VW := GetSystemMetrics( SM_CXVSCROLL );
60698 HH := GetSystemMetrics( SM_CYHSCROLL );
60699 VH := GetSystemMetrics( SM_CYVSCROLL );
60700 HW := GetSystemMetrics( SM_CXHSCROLL );
60701 if CR.Right + VW <= R.Right then
60702 begin
60703 Rgn1 := CreateRectRgn( CR.Right, CR.Top + VH, CR.Right + VW, CR.Bottom - VH );
60704 CombineRgn( Rgn, Rgn, Rgn1, RGN_DIFF );
60705 DeleteObject( Rgn1 );
60706 end;
60707 if CR.Bottom + HH <= R.Bottom then
60708 begin
60709 Rgn1 := CreateRectRgn( CR.Left + HW, CR.Bottom, CR.Right - HW, CR.Bottom + HH );
60710 CombineRgn( Rgn, Rgn, Rgn1, RGN_DIFF );
60711 DeleteObject( Rgn1 );
60712 end;
60713 end;
60714 Self_.Perform( WM_NCPAINT, Rgn, 0 );
60715 DeleteObject( Rgn ); // Unremarked By M.Gerasimov
60716 end;
60717 end;
60718 Result := False;
60719 end;
60722 //[function TControl.REGetTransparent]
60723 function TControl.REGetTransparent: Boolean;
60724 begin
60725 Result := Longbool(ExStyle and WS_EX_TRANSPARENT);
60726 end;
60729 //[procedure TControl.RESetTransparent]
60730 procedure TControl.RESetTransparent(const Value: Boolean);
60731 begin
60732 ExStyle := ExStyle or WS_EX_TRANSPARENT;
60733 fParent.AttachProc( WndProc_RichEdTransp_ParentPaint );
60734 AttachProc( WndProc_RichEdTransp_Update );
60735 fTransparent := Value;
60736 end;
60739 //[procedure TControl.RESetOnURL]
60740 procedure TControl.RESetOnURL(const Index: Integer; const Value: TOnEvent);
60741 begin
60742 if Index = 0 then
60743 fOnREOverURL := Value
60744 else
60745 fOnREURLClick := Value;
60746 RE_AutoURLDetect := assigned(fOnREOverURL) or assigned(fOnREURLClick);
60747 end;
60749 {$IFDEF F_P}
60750 //[function TControl.REGetOnURL]
60751 function TControl.REGetOnURL(const Index: Integer): TOnEvent;
60752 begin
60753 CASE Index OF
60754 0: Result := fOnREOverURL;
60755 else Result := fOnREURLClick;
60756 END;
60757 end;
60758 {$ENDIF F_P}
60761 //[function TControl.REGetLangOptions]
60762 function TControl.REGetLangOptions(const Index: Integer): Boolean;
60763 begin
60764 Result := LongBool( Perform( EM_GETLANGOPTIONS, 0, 0 ) and Index);
60765 end;
60768 //[procedure TControl.RESetLangOptions]
60769 procedure TControl.RESetLangOptions(const Index: Integer;
60770 const Value: Boolean);
60771 var Mask: Integer;
60772 begin
60773 Mask := -1;
60774 if not Value then Inc( Mask );
60775 Perform( EM_SETLANGOPTIONS, 0, Perform( EM_GETLANGOPTIONS, 0, 0 ) and
60776 not Index or (Mask and Index) );
60777 end;
60779 //[API _TrackMouseEvent]
60780 function _TrackMouseEvent(lpEventTrack: PTrackMouseEvent): BOOL;
60781 external cctrl name '_TrackMouseEvent';
60783 //[function DoTrackMouseEvent]
60784 function DoTrackMouseEvent(lpEventTrack: PTrackMouseEvent): BOOL;
60785 var FunTrack: function(lpEventTrack: PTrackMouseEvent): BOOL; stdcall;
60786 ComCtlModule: THandle;
60787 begin
60788 Result := FALSE;
60789 ComCtlModule := GetModuleHandle( cctrl );
60790 if ComCtlModule = 0 then Exit;
60791 FunTrack := GetProcAddress( ComCtlModule, '_TrackMouseEvent' );
60792 if not Assigned( FunTrack ) then Exit;
60793 Result := FunTrack( lpEventTrack );
60794 end;
60797 //[function WndProcMouseEnterLeave]
60798 function WndProcMouseEnterLeave( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
60799 var P: TPoint;
60800 MouseWasInControl: Boolean;
60801 Yes: Boolean;
60802 Track: TTrackMouseEvent;
60803 begin
60804 case Msg.message of
60805 WM_MOUSEFIRST..WM_MOUSELAST:
60806 begin
60807 MouseWasInControl := Self_.MouseInControl;
60808 if Assigned( Self_.fOnTestMouseOver ) then
60809 Yes := Self_.fOnTestMouseOver( Self_ )
60810 else
60811 begin
60812 GetCursorPos( P );
60813 P := Self_.Screen2Client( P );
60814 Yes := PointInRect( P, Self_.ClientRect );
60815 end;
60816 if MouseWasInControl <> Yes then
60817 begin
60818 Self_.Invalidate;
60819 if Yes then
60820 begin
60821 Self_.fMouseInControl := TRUE;
60822 if Assigned( Self_.fOnMouseEnter ) then
60823 Self_.fOnMouseEnter( Self_ );
60824 Track.cbSize := Sizeof( Track );
60825 Track.dwFlags := TME_LEAVE;
60826 Track.hwndTrack := Self_.Handle;
60827 //Track.dwHoverTime := 0;
60828 DoTrackMouseEvent( @ Track );
60829 Self_.Invalidate;
60831 else
60832 begin
60833 Self_.fMouseInControl := FALSE;
60834 Track.cbSize := Sizeof( Track );
60835 Track.dwFlags := TME_LEAVE or TME_CANCEL;
60836 Track.hwndTrack := Self_.Handle;
60837 //Track.dwHoverTime := 0;
60838 DoTrackMouseEvent( @ Track );
60839 if Assigned( Self_.fOnMouseLeave ) then
60840 Self_.fOnMouseLeave( Self_ );
60841 Self_.Invalidate;
60842 end;
60843 end;
60844 end;
60845 WM_MOUSELEAVE:
60846 begin
60847 if Self_.fMouseInControl then
60848 begin
60849 Self_.fMouseInControl := FALSE;
60850 if Assigned( Self_.fOnMouseLeave ) then
60851 Self_.fOnMouseLeave( Self_ );
60852 Self_.Invalidate;
60853 end;
60854 end;
60855 end;
60856 Result := False;
60857 end;
60859 //[procedure ProvideMouseEnterLeave]
60860 procedure ProvideMouseEnterLeave( Self_: PControl );
60861 begin
60862 InitCommonControls;
60863 Self_.AttachProc( WndProcMouseEnterLeave );
60864 Self_.Invalidate;
60865 end;
60867 //[procedure TControl.SetFlat]
60868 procedure TControl.SetFlat(const Value: Boolean);
60869 begin
60870 //if fFlat = Value then Exit;
60871 fFlat := Value;
60872 fMouseInControl := FALSE;
60873 ProvideMouseEnterLeave( @Self );
60874 Invalidate;
60875 end;
60877 //[procedure TControl.SetOnMouseEnter]
60878 procedure TControl.SetOnMouseEnter(const Value: TOnEvent);
60879 begin
60880 fOnMouseEnter := Value;
60881 ProvideMouseEnterLeave( @Self );
60882 end;
60884 //[procedure TControl.SetOnMouseLeave]
60885 procedure TControl.SetOnMouseLeave(const Value: TOnEvent);
60886 begin
60887 fOnMouseLeave := Value;
60888 ProvideMouseEnterLeave( @Self );
60889 end;
60891 //[procedure TControl.SetOnTestMouseOver]
60892 procedure TControl.SetOnTestMouseOver(const Value: TOnTestMouseOver);
60893 begin
60894 fOnTestMouseOver := Value;
60895 ProvideMouseEnterLeave( @Self );
60896 end;
60898 //[function WndProcEdTransparent]
60899 function WndProcEdTransparent( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
60900 begin
60901 if (Msg.message = WM_KEYDOWN) or
60902 (Msg.message = WM_MOUSEMOVE) and (GetKeyState( VK_LBUTTON ) < 0) or
60903 (Msg.message = WM_LBUTTONUP) or (Msg.message = WM_LBUTTONDOWN) then
60904 Self_.Invalidate;
60905 Result := False; // continue handling of a message anyway
60906 end;
60908 //[procedure TControl.EdSetTransparent]
60909 procedure TControl.EdSetTransparent(const Value: Boolean);
60910 begin
60911 Transparent := Value;
60912 AttachProc( WndProcEdTransparent );
60913 end;
60915 //[function WndProcSpeedButton]
60916 function WndProcSpeedButton( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
60917 begin
60918 Result := False;
60919 if Msg.message = WM_SETFOCUS then
60920 begin
60921 Result := TRUE;
60922 Rslt := 0;
60923 end;
60924 end;
60926 //[function TControl.LikeSpeedButton]
60927 function TControl.LikeSpeedButton: PControl;
60928 var Form: PControl;
60929 begin
60930 AttachProc( WndProcSpeedButton );
60931 fTabstop := False;
60932 Style := Style and not WS_TABSTOP;
60933 Form := ParentForm;
60934 if Form <> nil then
60935 if Form.fCurrentControl = @Self then
60936 begin
60937 Form.GotoControl( VK_TAB );
60938 if Form.fCurrentControl = @Self then
60939 Form.fCurrentControl := nil;
60940 end;
60941 Result := @Self;
60942 end;
60944 { -- Unicode -- }
60945 //[function TControl.SetUnicode]
60946 function TControl.SetUnicode(Unicode: Boolean): PControl;
60947 begin
60948 Perform( CCM_SETUNICODEFORMAT, Integer( Unicode ), 0 );
60949 Result := @ Self;
60950 end;
60952 { -- TabControl -- }
60954 //[function TControl.GetPages]
60955 function TControl.GetPages(Idx: Integer): PControl;
60956 var Item: TTCItem;
60957 begin
60958 Item.mask := TCIF_PARAM;
60959 if Perform( TCM_GETITEM, Idx, Integer( @Item ) ) = 0 then
60960 Result := nil
60961 else
60962 Result := Pointer( Item.lParam );
60963 end;
60965 //[function TControl.TCGetItemText]
60966 function TControl.TCGetItemText(Idx: Integer): String;
60967 var TI: TTCItem;
60968 Buffer: array[ 0..1023 ] of Char;
60969 begin
60970 TI.mask := TCIF_TEXT;
60971 TI.pszText := @Buffer[ 0 ];
60972 TI.cchTextMax := sizeof( Buffer );
60973 Buffer[ 0 ] := #0;
60974 Perform( TCM_GETITEM, Idx, Integer( @TI ) );
60975 Result := Buffer;
60976 end;
60978 //[procedure TControl.TCSetItemText]
60979 procedure TControl.TCSetItemText(Idx: Integer; const Value: String);
60980 var TI: TTCItem;
60981 begin
60982 TI.mask := TCIF_TEXT;
60983 TI.pszText := PChar( Value );
60984 Perform( TCM_SETITEM, Idx, Integer( @TI ) );
60985 end;
60987 //[function TControl.TCGetItemImgIDx]
60988 function TControl.TCGetItemImgIDx(Idx: Integer): Integer;
60989 var TI: TTCItem;
60990 begin
60991 TI.mask := TCIF_IMAGE;
60992 if Perform( TCM_GETITEM, Idx, Integer( @TI ) ) = 0 then
60993 Result := -1
60994 else
60995 Result := TI.iImage;
60996 end;
60998 //[procedure TControl.TCSetItemImgIdx]
60999 procedure TControl.TCSetItemImgIdx(Idx: Integer; const Value: Integer);
61000 var TI: TTCItem;
61001 begin
61002 TI.mask := TCIF_IMAGE;
61003 TI.iImage := Value;
61004 Perform( TCM_SETITEM, Idx, Integer( @TI ) );
61005 end;
61007 //[function TControl.TCGetItemRect]
61008 function TControl.TCGetItemRect(Idx: Integer): TRect;
61009 begin
61010 if Perform( TCM_GETITEMRECT, Idx, Integer( @Result ) ) = 0 then
61011 begin
61012 Result.Left := 0;
61013 Result.Right := 0;
61014 Result.Top := 0;
61015 Result.Bottom := 0;
61016 end;
61017 end;
61019 //[procedure TControl.TC_SetPadding]
61020 procedure TControl.TC_SetPadding(cx, cy: Integer);
61021 begin
61022 Perform( TCM_SETPADDING, 0, cx or (cy shl 16) );
61023 end;
61025 //[function TControl.TC_TabAtPos]
61026 function TControl.TC_TabAtPos(x, y: Integer): Integer;
61027 type TTCHittestInfo = packed record
61028 Pt: TPoint;
61029 Fl: DWORD;
61030 end;
61031 var HTI: TTCHitTestInfo;
61032 begin
61033 HTI.Pt.x := x;
61034 HTI.Pt.y := y;
61035 Result := Perform( TCM_HITTEST, 0, Integer( @HTI ) );
61036 end;
61038 //[function TControl.TC_DisplayRect]
61039 function TControl.TC_DisplayRect: TRect;
61040 begin
61041 Windows.GetClientRect( fHandle, Result );
61042 Perform( TCM_ADJUSTRECT, 0, Integer( @Result ) );
61043 end;
61045 //[function TControl.TC_IndexOf]
61046 function TControl.TC_IndexOf(const S: String): Integer;
61047 begin
61048 Result := TC_SearchFor( S, -1, FALSE );
61049 end;
61051 //[function TControl.TC_SearchFor]
61052 function TControl.TC_SearchFor(const S: String; StartAfter: Integer;
61053 Partial: Boolean): Integer;
61054 var I: Integer;
61055 begin
61056 Result := -1;
61057 for I := StartAfter+1 to Count-1 do
61058 begin
61059 if Partial and ( Copy( TC_Items[ I ], 1, Length( S ) ) = S ) or
61060 ( TC_Items[ I ] = S ) then
61061 begin
61062 Result := I;
61063 break;
61064 end;
61065 end;
61066 end;
61068 //[function TControl.TC_Insert]
61069 function TControl.TC_Insert(Idx: Integer; const TabText: String;
61070 TabImgIdx: Integer): PControl;
61071 var TI: TTCItem;
61072 begin
61073 Result := NewPanel( @Self, esNone );
61074 Result.FAlign := caClient;
61075 Result.fNotUseAlign := True;
61076 Result.fVisibleWoParent := TRUE;
61077 Result.Visible := Count = 0;
61078 TI.mask := TCIF_TEXT or TCIF_IMAGE or TCIF_PARAM;
61079 TI.iImage := TabImgIdx;
61080 TI.pszText := PChar( TabText );
61081 TI.lParam := Integer( Result );
61082 Perform( TCM_INSERTITEM, Idx, Integer( @TI ) );
61083 Result.BoundsRect := TC_DisplayRect;
61084 end;
61086 //[procedure TControl.TC_Delete]
61087 procedure TControl.TC_Delete(Idx: Integer);
61088 var Page: PControl;
61089 begin
61090 Page := TC_Pages[ Idx ];
61091 if Page = nil then Exit;
61092 Perform( TCM_DELETEITEM, Idx, 0 );
61093 Page.Free;
61094 end;
61096 { -- TreeView -- }
61098 //[function TControl.TVGetItemIdx]
61099 function TControl.TVGetItemIdx(const Index: Integer): THandle;
61100 begin
61101 Result := Perform( TVM_GETNEXTITEM, Index, 0 );
61102 end;
61104 //[procedure TControl.TVSetItemIdx]
61105 procedure TControl.TVSetItemIdx(const Index: Integer;
61106 const Value: THandle);
61107 begin
61108 Perform( TVM_SELECTITEM, Index, Value );
61109 end;
61111 //[function TControl.TVGetItemNext]
61112 function TControl.TVGetItemNext(Item: THandle; const Index: Integer): THandle;
61113 begin
61114 Result := Perform( TVM_GETNEXTITEM, Index, Item );
61115 end;
61117 //[function TControl.TVGetItemRect]
61118 function TControl.TVGetItemRect(Item: THandle; TextOnly: Boolean): TRect;
61119 begin
61120 Result.Left := Item;
61121 if Perform( TVM_GETITEMRECT, Integer( TextOnly ), Integer( @Result ) ) = 0 then
61122 begin
61123 Result.Left := 0;
61124 Result.Right := 0;
61125 Result.Top := 0;
61126 Result.Bottom := 0;
61127 end;
61128 end;
61130 //[function TControl.TVGetItemVisible]
61131 function TControl.TVGetItemVisible(Item: THandle): Boolean;
61132 var R: TRect;
61133 begin
61134 R := TVItemRect[ Item, False ];
61135 Result := R.Bottom > R.Top;
61136 end;
61138 //[procedure TControl.TVSetItemVisible]
61139 procedure TControl.TVSetItemVisible(Item: THandle; const Value: Boolean);
61140 begin
61141 if Value then
61142 Perform( TVM_ENSUREVISIBLE, 0, Item );
61143 end;
61145 //[function TControl.TVGetItemStateFlg]
61146 function TControl.TVGetItemStateFlg(Item: THandle; const Index: Integer): Boolean;
61147 var TVI: TTVItem;
61148 begin
61149 TVI.mask := TVIF_HANDLE or TVIF_STATE;
61150 TVI.hItem := Item;
61151 TVI.stateMask := Index;
61152 Result := False;
61153 if Perform( TVM_GETITEM, 0, Integer( @TVI ) ) <> 0 then
61154 Result := (TVI.state and Index) <> 0;
61155 end;
61157 //[procedure TControl.TVSetItemStateFlg]
61158 procedure TControl.TVSetItemStateFlg(Item: THandle; const Index: Integer;
61159 const Value: Boolean);
61160 var TVI: TTVItem;
61161 begin
61162 TVI.mask := TVIF_HANDLE or TVIF_STATE;
61163 TVI.hItem := Item;
61164 TVI.stateMask := Index;
61165 TVI.state := $FFFFFFFF and Index;
61166 if not Value then
61167 TVI.state := 0;
61168 Perform( TVM_SETITEM, 0, Integer( @TVI ) );
61169 end;
61171 //[function TControl.TVGetItemImage]
61172 function TControl.TVGetItemImage(Item: THandle; const Index: Integer): Integer;
61173 var TVI: TTVItem;
61174 begin
61175 TVI.mask := TVIF_HANDLE or Loword( Index );
61176 TVI.hItem := Item;
61177 if Hiword( Index ) <> 0 then
61178 begin
61179 TVI.mask := TVIF_STATE or TVIF_HANDLE;
61180 TVI.stateMask := Loword( Index );
61181 end;
61182 Result := -1;
61183 if Perform( TVM_GETITEM, 0, Integer( @TVI ) ) <> 0 then
61184 begin
61185 if Hiword( Index ) <> 0 then
61186 Result := (TVI.state shr Hiword( Index )) and $F
61187 else
61188 if Loword( Index ) = TVIF_IMAGE then
61189 Result := TVI.iImage
61190 else
61191 Result := TVI.iSelectedImage;
61192 end;
61193 end;
61195 //[procedure TControl.TVSetItemImage]
61196 procedure TControl.TVSetItemImage(Item: THandle; const Index: Integer;
61197 const Value: Integer);
61198 var TVI: TTVItem;
61199 begin
61200 TVI.mask := TVIF_HANDLE or Loword( Index );
61201 TVI.hItem := Item;
61202 TVI.iImage := Value;
61203 TVI.iSelectedImage := Value;
61204 if Hiword( Index ) <> 0 then
61205 begin
61206 TVI.mask := TVIF_STATE or TVIF_HANDLE;
61207 TVI.stateMask := Loword( Index );
61208 TVI.state := Value shl Hiword( Index );
61209 end;
61210 Perform( TVM_SETITEM, 0, Integer( @TVI ) );
61211 end;
61213 //[function TControl.TVGetItemText]
61214 function TControl.TVGetItemText(Item: THandle): String;
61215 var TVI: TTVItem;
61216 Buffer: array[ 0..4095 ] of Char;
61217 begin
61218 TVI.mask := TVIF_HANDLE or TVIF_TEXT;
61219 TVI.hItem := Item;
61220 TVI.pszText := @Buffer[ 0 ];
61221 Buffer[ 0 ] := #0;
61222 TVI.cchTextMax := Sizeof( Buffer );
61223 Perform( TVM_GETITEM, 0, Integer( @TVI ) );
61224 Result := Buffer;
61225 end;
61227 //[procedure TControl.TVSetItemText]
61228 procedure TControl.TVSetItemText(Item: THandle; const Value: String);
61229 var TVI: TTVItem;
61230 begin
61231 TVI.mask := TVIF_HANDLE or TVIF_TEXT;
61232 TVI.hItem := Item;
61233 TVI.pszText := PChar( Value );
61234 Perform( TVM_SETITEM, 0, Integer( @TVI ) );
61235 end;
61237 {$IFNDEF _FPC}
61238 {$IFNDEF _D2}
61239 //[function TControl.TVGetItemTextW]
61240 function TControl.TVGetItemTextW(Item: THandle): WideString;
61241 var TVI: TTVItemW;
61242 Buffer: array[ 0..4095 ] of WideChar;
61243 begin
61244 TVI.mask := TVIF_HANDLE or TVIF_TEXT;
61245 TVI.hItem := Item;
61246 TVI.pszText := @Buffer[ 0 ];
61247 Buffer[ 0 ] := #0;
61248 TVI.cchTextMax := High( Buffer ) + 1;
61249 Perform( TVM_GETITEMW, 0, Integer( @TVI ) );
61250 Result := Buffer;
61251 end;
61253 //[procedure TControl.TVSetItemTextW]
61254 procedure TControl.TVSetItemTextW(Item: THandle; const Value: WideString);
61255 var TVI: TTVItemW;
61256 begin
61257 TVI.mask := TVIF_HANDLE or TVIF_TEXT;
61258 TVI.hItem := Item;
61259 TVI.pszText := PWideChar( Value );
61260 Perform( TVM_SETITEMW, 0, Integer( @TVI ) );
61261 end;
61262 {$ENDIF _D2}
61263 {$ENDIF _FPC}
61265 //[function TControl.TVItemPath]
61266 function TControl.TVItemPath(Item: THandle; Delimiter: Char): String;
61267 begin
61268 if Item = 0 then
61269 Item := TVSelected;
61270 Result := '';
61271 while Item <> 0 do
61272 begin
61273 if Result <> '' then
61274 Result := Delimiter + Result;
61275 Result := TVItemText[ Item ] + Result;
61276 Item := TVItemParent[ Item ];
61277 end;
61278 end;
61280 {$IFNDEF _FPC}
61281 {$IFNDEF _D2}
61282 //[function TControl.TVItemPathW]
61283 function TControl.TVItemPathW(Item: THandle;
61284 Delimiter: WideChar): WideString;
61285 begin
61286 if Item = 0 then
61287 Item := TVSelected;
61288 Result := '';
61289 while Item <> 0 do
61290 begin
61291 if Result <> '' then
61292 Result := {$IFDEF _D3} '' + {$ENDIF} Delimiter + Result;
61293 Result := TVItemTextW[ Item ] + Result;
61294 Item := TVItemParent[ Item ];
61295 end;
61296 end;
61297 {$ENDIF _D2}
61298 {$ENDIF _FPC}
61300 //[function TControl.TV_GetItemHasChildren]
61301 function TControl.TV_GetItemHasChildren(Item: THandle): Boolean;
61302 var TVI: TTVItem;
61303 begin
61304 TVI.mask := TVIF_HANDLE or TVIF_CHILDREN;
61305 TVI.hItem := Item;
61306 Perform( TVM_GETITEM, 0, Integer( @TVI ) );
61307 Result := TVI.cChildren = 1;
61308 end;
61310 //[procedure TControl.TV_GetItemChildCount]
61311 function TControl.TV_GetItemChildCount(Item: THandle): Integer;
61312 var Node: THandle;
61313 begin
61314 Result := 0;
61315 Node := TVItemChild[ Item ];
61316 while Node <> 0 do
61317 begin
61318 Inc( Result );
61319 Node := TVItemNext[ Node ];
61320 end;
61321 end;
61323 //[procedure TControl.TV_SetItemHasChildren]
61324 procedure TControl.TV_SetItemHasChildren(Item: THandle;
61325 const Value: Boolean);
61326 var TVI: TTVItem;
61327 begin
61328 TVI.mask := TVIF_HANDLE or TVIF_CHILDREN;
61329 TVI.hItem := Item;
61330 TVI.cChildren := 1 and Integer( Value );
61331 Perform( TVM_SETITEM, 0, Integer( @TVI ) );
61332 end;
61334 //[function TControl.TVItemAtPos]
61335 function TControl.TVItemAtPos(x, y: Integer; var Where: DWORD): THandle;
61336 var HTI: TTVHitTestInfo;
61337 begin
61338 HTI.pt.x := x;
61339 HTI.pt.y := y;
61340 Result := Perform( TVM_HITTEST, 0, Integer( @HTI ) );
61341 Where := HTI.fl;
61342 end;
61344 type
61345 TTVInsertStruct = packed Record
61346 hParent: THandle;
61347 hAfter : THandle;
61348 item: TTVItem;
61349 end;
61350 TTVInsertStructEx = packed Record
61351 hParent: THandle;
61352 hAfter : THandle;
61353 item: TTVItemEx;
61354 end;
61356 //[function TControl.TVInsert]
61357 function TControl.TVInsert(nParent, nAfter: THandle;
61358 const Txt: String): THandle;
61359 var TVIns: TTVInsertStruct;
61360 begin
61361 TVIns.hParent := nParent;
61362 TVIns.hAfter := nAfter;
61363 TVIns.item.mask := TVIF_TEXT;
61364 TVIns.item.pszText := PChar( Txt );
61365 Result := Perform( TVM_INSERTITEM, 0, Integer( @TVIns ) );
61366 Invalidate;
61367 end;
61369 {$IFNDEF _FPC}
61370 {$IFNDEF _D2}
61371 type
61372 TTVInsertStructW = packed Record
61373 hParent: THandle;
61374 hAfter : THandle;
61375 item: TTVItemW;
61376 end;
61377 TTVInsertStructExW = packed Record
61378 hParent: THandle;
61379 hAfter : THandle;
61380 item: TTVItemExW;
61381 end;
61383 //[function TControl.TVInsertW]
61384 function TControl.TVInsertW(nParent, nAfter: THandle;
61385 const Txt: WideString): THandle;
61386 var TVIns: TTVInsertStructW;
61387 begin
61388 TVIns.hParent := nParent;
61389 TVIns.hAfter := nAfter;
61390 TVIns.item.mask := TVIF_TEXT;
61391 if Txt = '' then TVIns.item.pszText := nil
61392 else TVIns.item.pszText := PWideChar( @ Txt[ 1 ] );
61393 Result := Perform( TVM_INSERTITEMW, 0, Integer( @ TVIns ) );
61394 Invalidate;
61395 end;
61396 {$ENDIF _D2}
61397 {$ENDIF _FPC}
61399 //[procedure TControl.TVExpand]
61400 procedure TControl.TVExpand(Item: THandle; Flags: DWORD);
61401 begin
61402 Perform( TVM_EXPAND, Flags, Item );
61403 end;
61405 //[procedure TControl.TVSort]
61406 procedure TControl.TVSort( N: THandle );
61407 var a: Cardinal;
61408 b: Boolean;
61409 begin
61410 b := N = 0;
61411 if b then
61412 begin
61413 N := TVRoot;
61414 end;
61415 while N <> 0 do
61416 begin
61417 a := TVItemChild[N];
61418 if a > 0 then
61419 TVSort(a);
61420 Perform(TVM_SORTCHILDREN, 0, N);
61421 N := TVItemNext[N];
61422 end;
61423 if b then //moved by Truf
61424 Perform(TVM_SORTCHILDREN, 0, 0); //+ by YS
61425 end;
61427 //[procedure TControl.TVDelete]
61428 procedure TControl.TVDelete(Item: THandle);
61429 begin
61430 Perform( TVM_DELETEITEM, 0, Item );
61431 Invalidate;
61432 end;
61434 //[function TControl.TVGetItemData]
61435 function TControl.TVGetItemData(Item: THandle): Pointer;
61436 var TVI: TTVItem;
61437 begin
61438 TVI.mask := TVIF_HANDLE or TVIF_PARAM;
61439 TVI.hItem := Item;
61440 Result := nil;
61441 if Perform( TVM_GETITEM, 0, Integer( @TVI ) ) <> 0 then
61442 Result := Pointer( TVI.lParam );
61443 end;
61445 //[procedure TControl.TVSetItemData]
61446 procedure TControl.TVSetItemData(Item: THandle; const Value: Pointer);
61447 var TVI: TTVItem;
61448 begin
61449 TVI.mask := TVIF_HANDLE or TVIF_PARAM;
61450 TVI.hItem := Item;
61451 TVI.lParam := Integer( Value );
61452 Perform( TVM_SETITEM, 0, Integer( @TVI ) );
61453 end;
61455 //[procedure TControl.TVEditItem]
61456 procedure TControl.TVEditItem(Item: THandle);
61457 begin
61458 Perform( TVM_EDITLABEL, 0, Item );
61459 end;
61461 //[procedure TControl.TVStopEdit]
61462 procedure TControl.TVStopEdit(Cancel: Boolean);
61463 begin
61464 Perform( TVM_ENDEDITLABELNOW, Integer( Cancel ), 0 );
61465 end;
61467 //[function WndProcTVRightClickSelect]
61468 function WndProcTVRightClickSelect( Sender: PControl; var Msg: TMsg; var R: Integer ): Boolean;
61469 var I: Integer;
61470 Where: DWORD;
61471 begin
61472 if Msg.message = WM_RBUTTONDOWN then
61473 begin
61474 I := Sender.TVItemAtPos( SmallInt( Msg.lParam and $FFFF ),
61475 SmallInt( Msg.lParam shr 16 ), Where );
61476 if I <> 0 then
61477 Sender.TVSelected := I;
61478 end;
61479 Result := FALSE;
61480 end;
61482 //[procedure TControl.SetTVRightClickSelect]
61483 procedure TControl.SetTVRightClickSelect(const Value: Boolean);
61484 begin
61485 fTVRightClickSelect := Value;
61486 if Value then
61487 AttachProc( @WndProcTVRightClickSelect );
61488 end;
61490 //[procedure TControl.SetOnTVDelete]
61491 procedure TControl.SetOnTVDelete( const Value: TOnTVDelete );
61492 begin
61493 fOnTVDelete := Value;
61494 if fParent <> nil then
61495 begin
61496 fParent.Add2AutoFreeEx( Clear );
61497 fParent.DetachProc( WndProcNotify );
61498 fParent.AttachProcEx( WndProcNotify, TRUE );
61499 end;
61500 AttachProcEx( ProcTVDeleteItem, TRUE );
61501 end;
61503 //[function Clipboard2Text]
61504 function Clipboard2Text: String;
61505 var gbl: THandle;
61506 str: PChar;
61507 begin
61508 Result := '';
61509 if OpenClipboard( 0 ) then
61510 begin
61511 if IsClipboardFormatAvailable( CF_TEXT ) then
61512 begin
61513 gbl := GetClipboardData( CF_TEXT );
61514 if gbl <> 0 then
61515 begin
61516 str := GlobalLock( gbl );
61517 if str <> nil then
61518 begin
61519 Result := str;
61520 GlobalUnlock( gbl );
61521 end;
61522 end;
61523 end;
61524 CloseClipboard;
61525 end;
61526 end;
61529 {$IFNDEF _D2}
61530 //[function Clipboard2WText]
61531 function Clipboard2WText: WideString;
61532 var gbl: THandle;
61533 str: PWideChar;
61534 begin
61535 Result := '';
61536 if OpenClipboard( 0 ) then
61537 begin
61538 if IsClipboardFormatAvailable( CF_UNICODETEXT ) then
61539 begin
61540 gbl := GetClipboardData( CF_UNICODETEXT );
61541 if gbl <> 0 then
61542 begin
61543 str := GlobalLock( gbl );
61544 if str <> nil then
61545 begin
61546 Result := str;
61547 GlobalUnlock( gbl );
61548 end;
61549 end;
61550 end;
61551 CloseClipboard;
61552 end;
61553 end;
61554 {$ENDIF}
61557 //[function Text2Clipboard]
61558 function Text2Clipboard( const S: String ): Boolean;
61559 var gbl: THandle;
61560 str: PChar;
61561 begin
61562 Result := False;
61563 if not OpenClipboard( 0 ) then Exit;
61564 EmptyClipboard;
61565 if S <> '' then
61566 begin
61567 gbl := GlobalAlloc( GMEM_DDESHARE, Length( S ) + 1 );
61568 if gbl <> 0 then
61569 begin
61570 str := GlobalLock( gbl );
61571 Move( S[ 1 ], str^, Length( S ) + 1 );
61572 GlobalUnlock( gbl );
61573 Result := SetClipboardData( CF_TEXT, gbl ) <> 0;
61574 end;
61576 else
61577 Result := True;
61578 CloseClipboard;
61579 end;
61582 {$IFNDEF _D2}
61583 //[function WText2Clipboard]
61584 function WText2Clipboard( const WS: WideString ): Boolean;
61585 var gbl: THandle;
61586 str: PChar;
61587 begin
61588 Result := False;
61589 if not OpenClipboard( 0 ) then Exit;
61590 EmptyClipboard;
61591 if WS <> '' then
61592 begin
61593 gbl := GlobalAlloc( GMEM_DDESHARE, (Length( WS ) + 1) * 2 );
61594 if gbl <> 0 then
61595 begin
61596 str := GlobalLock( gbl );
61597 Move( WS[ 1 ], str^, (Length( WS ) + 1) * 2 );
61598 GlobalUnlock( gbl );
61599 Result := SetClipboardData( CF_UNICODETEXT, gbl ) <> 0;
61600 end;
61602 else
61603 Result := True;
61604 CloseClipboard;
61605 end;
61606 {$ENDIF}
61609 //[function TControl.Size]
61610 function TControl.Size(W, H: Integer): PControl;
61611 var C, P: PControl;
61612 dW, dH: Integer;
61613 begin
61614 C := @Self;
61615 while True do
61616 begin
61617 dW := 0; dH := 0;
61618 P := C.FParent;
61619 if C.ToBeVisible {or C.fCreateHidden {or (P <> nil) and (P.fVisible)} then
61620 begin
61621 if C.fAlign in [caLeft, caRight, caClient] then
61622 begin
61623 if H > 0 then
61624 begin
61625 dH := H - C.Height; H := 0;
61626 end;
61627 end;
61628 if C.fAlign in [caTop, caBottom, caClient] then
61629 begin
61630 if W > 0 then
61631 begin
61632 dW := W - C.Width; W := 0;
61633 end;
61634 end;
61635 end;
61636 if (W > 0) or (H > 0) then
61637 begin
61638 C.SetSize( W, H );
61639 if (P <> nil) // {Ralf Junker}
61640 and not P.IsApplet then
61641 C.ResizeParent;
61643 if P <> nil then
61644 begin
61645 if not (C.FAlign in [caLeft,caRight,caClient]) then
61646 C.ResizeParentRight;
61647 if not (C.FAlign in [caTop,caBottom,caClient]) then
61648 C.ResizeParentBottom;
61649 end;
61651 end;
61652 if (dW = 0) and (dH = 0) then break;
61653 C := P; //C.FParent;
61654 if C = nil then break;
61655 //if not C.fIsControl then break;
61656 if C.IsApplet then break;
61657 W := C.Width + dW;
61658 H := C.Height + dH;
61659 end;
61660 Result := @Self;
61661 end;
61663 //[procedure AutoSzProc]
61664 procedure AutoSzProc( Self_: PControl );
61665 var DeltaX, DeltaY: Integer;
61666 SZ: TSize; PT: TPoint;
61667 Txt: String;
61668 Chg: Boolean;
61669 begin
61670 Txt := Self_.fCaption;
61671 SZ.cx := 0;
61672 SZ.cy := 0;
61673 if Txt <> '' then
61674 begin
61675 if Assigned( Self_.fFont ) then
61676 if Self_.fFont.fData.Font.Italic then
61677 Txt := Txt + ' ';
61678 Self_.GetWindowHandle; // this line must be here.
61679 //-- otherwise, when handle is not yet allocated,
61680 // it is requested in TCanvas.GetHandle, and in result
61681 // of unpredictable recursion some memory can be currupted.
61682 Self_.Canvas.TextArea( Txt, SZ, PT );
61683 end;
61684 Chg := FALSE;
61685 if Self_.FAlign in [ caNone, caLeft, caRight ] then
61686 begin
61687 DeltaX := Self_.fCommandActions.aAutoSzX;
61688 if DeltaX > 0 then
61689 begin
61690 Self_.Width := SZ.cx + DeltaX;
61691 Chg := TRUE;
61692 end;
61693 end;
61694 if Self_.FAlign in [ caNone, caTop, caBottom ] then
61695 begin
61696 DeltaY := Self_.fCommandActions.aAutoSzY;
61697 if DeltaY > 0 then
61698 begin
61699 Self_.Height := SZ.cy + DeltaY;
61700 Chg := TRUE;
61701 end;
61702 end;
61703 if Chg then
61704 begin
61705 if Self_.fParent <> nil then
61706 Global_Align( Self_.fParent );
61707 Global_Align( Self_ );
61708 end;
61709 end;
61711 //[function TControl.AutoSize]
61712 function TControl.AutoSize(AutoSzOn: Boolean): PControl;
61713 begin
61714 if AutoSzOn then
61715 begin
61716 fAutoSize := AutoSzProc;
61717 fAutoSize( @Self );
61719 else
61720 fAutoSize := nil;
61721 Result := @Self;
61722 end;
61724 //[function TControl.IsAutoSize]
61725 function TControl.IsAutoSize: Boolean;
61726 begin
61727 Result := Assigned( fAutoSize );
61728 end;
61731 //[function TControl.GetToBeVisible]
61732 function TControl.GetToBeVisible: Boolean;
61733 begin
61734 Result := fVisible or fCreateHidden or fVisibleWoParent;
61735 if fIsControl then
61736 if Parent <> nil then
61737 begin
61738 if fVisibleWoParent then
61739 Result := fVisible
61740 else
61741 begin
61742 Parent.Visible; // needed to provide correct fVisible for a form!
61743 Result := Result and Parent.ToBeVisible;
61744 end;
61745 end;
61746 end;
61748 { -- TTree -- }
61750 {$IFDEF USE_CONSTRUCTORS}
61751 //[function NewTree]
61752 function NewTree( AParent: PTree; const AName: String ): PTree;
61753 begin
61754 New( Result, CreateTree( AParent, AName ) );
61755 end;
61756 //[END NewTree]
61757 {$ELSE not_USE_CONSTRUCTORS}
61758 //[function NewTree]
61759 function NewTree( AParent: PTree; const AName: String ): PTree;
61760 begin
61762 New( Result, Create );
61763 {+}{++}(*Result := PTree.Create;*){--}
61764 if AParent <> nil then
61765 AParent.Add( Result );
61766 Result.fParent := AParent;
61767 Result.fName := AName;
61768 end;
61769 //[END NewTree]
61770 {$ENDIF USE_CONSTRUCTORS}
61772 { TTree }
61774 //[procedure TTree.Add]
61775 procedure TTree.Add(Node: PTree);
61776 var Previous: PTree;
61777 begin
61778 Node.Unlink;
61779 if fChildren = nil then
61780 fChildren := NewList;
61781 Previous := nil;
61782 if fChildren.fCount > 0 then
61783 Previous := fChildren.fItems[ fChildren.fCount - 1 ];
61784 if Previous <> nil then
61785 begin
61786 Previous.fNext := Node;
61787 Node.fPrev := Previous;
61788 end;
61789 fChildren.Add( Node );
61790 Node.fParent := @Self;
61791 end;
61793 //[procedure TTree.Clear]
61794 procedure TTree.Clear;
61795 var I: Integer;
61796 begin
61797 if fChildren = nil then Exit;
61798 for I := fChildren.fCount - 1 downto 0 do
61799 PTree( fChildren.fItems[ I ] ).Free;
61800 end;
61802 {$IFDEF USE_CONSTRUCTORS}
61803 //[constructor TTree.CreateTree]
61804 constructor TTree.CreateTree(AParent: PTree; const AName: String);
61805 begin
61806 inherited Create;
61807 if AParent <> nil then
61808 AParent.Add( @Self );
61809 fParent := AParent;
61810 fName := AName;
61811 end;
61812 {$ENDIF}
61814 //[destructor TTree.Destroy]
61815 destructor TTree.Destroy;
61816 begin
61817 Unlink;
61818 Clear;
61819 fName := '';
61820 inherited;
61821 end;
61823 //[function TTree.GetCount]
61824 function TTree.GetCount: Integer;
61825 begin
61826 Result := 0;
61827 if fChildren = nil then Exit;
61828 Result := fChildren.fCount;
61829 end;
61831 //[function TTree.GetIndexAmongSiblings]
61832 function TTree.GetIndexAmongSiblings: Integer;
61833 begin
61834 Result := -1;
61835 if fParent = nil then Exit;
61836 Result := fParent.fChildren.IndexOf( @Self );
61837 end;
61839 //[function TTree.GetItems]
61840 function TTree.GetItems(Idx: Integer): PTree;
61841 begin
61842 Result := nil;
61843 if fChildren = nil then Exit;
61844 Result := fChildren.Items[ Idx ];
61845 end;
61847 //[function TTree.GetLevel]
61848 function TTree.GetLevel: Integer;
61849 var Node: PTree;
61850 begin
61851 Result := 0;
61852 Node := fParent;
61853 while Node <> nil do
61854 begin
61855 Inc( Result );
61856 Node := Node.fParent;
61857 end;
61858 end;
61860 //[function TTree.GetRoot]
61861 function TTree.GetRoot: PTree;
61862 begin
61863 Result := @Self;
61864 while Result.fParent <> nil do
61865 Result := Result.fParent;
61866 end;
61868 //[function TTree.GetTotal]
61869 function TTree.GetTotal: Integer;
61870 var I: Integer;
61871 begin
61872 Result := Count;
61873 if Result <> 0 then
61874 begin
61875 for I := 0 to Count - 1 do
61876 Result := Result + Items[ I ].Total;
61877 end;
61878 end;
61880 //[procedure TTree.Init]
61881 procedure TTree.Init;
61882 begin
61883 if FParent <> nil then
61884 FParent.Add( @Self );
61885 end;
61887 //[procedure TTree.Insert]
61888 procedure TTree.Insert(Before, Node: PTree);
61889 var Previous: PTree;
61890 begin
61891 Node.Unlink;
61892 if fChildren = nil then
61893 fChildren := NewList;
61894 Previous := nil;
61895 if Before <> nil then
61896 Previous := Before.fPrev;
61897 if Previous <> nil then
61898 begin
61899 Previous.fNext := Node;
61900 Node.fPrev := Previous;
61901 end;
61902 if Before <> nil then
61903 begin
61904 Node.fNext := Before;
61905 Before.fPrev := Node;
61906 fChildren.Insert( fChildren.IndexOf( Before ), Node );
61908 else
61909 fChildren.Add( Node );
61910 Node.fParent := @Self;
61911 end;
61913 //[function CompareTreeNodes]
61914 function CompareTreeNodes( const Data: Pointer; const e1, e2: DWORD ): Integer;
61915 var List: PList;
61916 begin
61917 List := Data;
61918 Result := AnsiCompareStr( PTree( List.fItems[ e1 ] ).fName,
61919 PTree( List.fItems[ e2 ] ).fName );
61920 end;
61922 //[procedure SwapTreeNodes]
61923 procedure SwapTreeNodes( const Data: Pointer; const e1, e2: DWORD );
61924 var List: PList;
61925 begin
61926 List := Data;
61927 List.Swap( e1, e2 );
61928 end;
61930 //[procedure TTree.SwapNodes]
61931 procedure TTree.SwapNodes( i1, i2: Integer );
61932 begin
61933 fChildren.Swap( i1, i2 );
61934 end;
61936 //[procedure TTree.SortByName]
61937 procedure TTree.SortByName;
61938 begin
61939 if Count <= 1 then Exit;
61940 SortData( fChildren, fChildren.fCount, CompareTreeNodes, SwapTreeNodes );
61941 end;
61943 //[procedure TTree.Unlink]
61944 procedure TTree.Unlink;
61945 var I: Integer;
61946 begin
61947 if fPrev <> nil then
61948 fPrev.fNext := fNext;
61949 if fNext <> nil then
61950 fNext.fPrev := fPrev;
61951 if (fParent <> nil) then
61952 begin
61953 I := fParent.fChildren.IndexOf( @Self );
61954 fParent.fChildren.Delete( I );
61955 if fParent.fChildren.fCount = 0 then
61956 begin
61957 fParent.fChildren.Free;
61958 fParent.fChildren := nil;
61959 end;
61960 end;
61961 fPrev := nil;
61962 fNext := nil;
61963 fParent := nil;
61964 end;
61966 //[function TTree.IsParentOfNode]
61967 function TTree.IsParentOfNode(Node: PTree): Boolean;
61968 begin
61969 Result := TRUE;
61970 while Node <> nil do
61971 begin
61972 if Node = @ Self then Exit;
61973 Node := Node.Parent;
61974 end;
61975 Result := FALSE;
61976 end;
61978 //[function TTree.IndexOf]
61979 function TTree.IndexOf(Node: PTree): Integer;
61980 begin
61981 Result := -1;
61982 if not IsParentOfNode( Node ) then Exit;
61983 while Node <> @ Self do
61984 begin
61985 Inc( Result );
61986 while Node.PrevSibling <> nil do
61987 begin
61988 Node := Node.PrevSibling;
61989 Inc( Result, 1 + Node.Total );
61990 end;
61991 Node := Node.Parent;
61992 end;
61993 end;
61996 //[procedure TControl.ProcessPendingMessages]
61997 procedure TControl.ProcessPendingMessages;
61998 var Msg: TMsg;
61999 begin
62000 if LOWORD( GetQueueStatus( QS_ALLINPUT ) ) <> 0 then
62001 if PeekMessage( Msg, 0, 0, 0, PM_NOREMOVE {or PM_NOYIELD} )
62002 or PeekMessage( Msg, HWnd(-1), 0, 0, PM_NOREMOVE {or PM_NOYIELD} )
62003 then
62004 Applet.ProcessMessages;
62005 end;
62007 //[procedure TControl.ProcessPaintMessages]
62008 procedure TControl.ProcessPaintMessages;
62009 var Msg: TMsg;
62010 begin
62011 while PeekMessage( Msg, Handle, 15, 15, PM_NOREMOVE ) do
62012 //while GetQueueStatus( QS_PAINT ) <> 0 do
62013 Applet.ProcessMessage;
62014 end;
62024 ///////////////////////////////////////////////////////////////////////
62027 // W I N D O W S
62030 ///////////////////////////////////////////////////////////////////////
62034 { -- Set of window-related utility functions. -- }
62035 type
62036 PGUIThreadInfo = ^TGUIThreadInfo;
62037 tagGUITHREADINFO = packed record
62038 cbSize: DWORD;
62039 flags: DWORD;
62040 hwndActive: HWND;
62041 hwndFocus: HWND;
62042 hwndCapture: HWND;
62043 hwndMenuOwner: HWND;
62044 hwndMoveSize: HWND;
62045 hwndCaret: HWND;
62046 rcCaret: TRect;
62047 end;
62048 TGUIThreadInfo = tagGUITHREADINFO;
62050 const
62051 GUI_CARETBLINKING = $00000001;
62052 GUI_INMOVESIZE = $00000002;
62053 GUI_INMENUMODE = $00000004;
62054 GUI_SYSTEMMENUMODE = $00000008;
62055 GUI_POPUPMENUMODE = $00000010;
62057 {function GetGUIThreadInfo (idThread: DWORD; var pgui: TGUIThreadinfo): BOOL; stdcall;
62058 external user32 name 'GetGUIThreadInfo';}
62060 type TGUIThreadInfo_Proc = function( ThreadID: THandle; var GTI: TGUIThreadInfo )
62061 : Boolean; stdcall;
62063 var Proc_GetGUIThreadInfo: TGuiThreadInfo_Proc;
62065 //[function GetWindowChild]
62066 function GetWindowChild( Wnd: HWnd; Kind: TWindowChildKind ): HWnd;
62067 var GTI: TGuiThreadInfo;
62068 ThreadID: THandle;
62069 Module: THandle;
62070 begin
62071 if not Assigned( Proc_GetGUIThreadInfo ) then
62072 begin
62073 Module := GetModuleHandle( 'User32' );
62074 Proc_GetGUIThreadInfo := GetProcAddress( Module, 'GetGUIThreadInfoA' );
62075 if not Assigned( Proc_GetGUIThreadInfo ) then
62076 Proc_GetGUIThreadInfo := Pointer( -1 );
62077 end;
62078 Result := Wnd;
62079 if Integer( @Proc_GetGUIThreadInfo ) = -1 then
62080 Exit;
62081 Result := 0;
62082 if Wnd = 0 then
62083 ThreadID := GetCurrentThreadID
62084 else
62085 ThreadID := GetWindowThreadProcessID( Wnd, nil );
62086 if ThreadID = 0 then Exit;
62087 GTI.cbSize := Sizeof( GTI );
62088 if Proc_GetGUIThreadInfo( ThreadId, GTI ) then
62089 begin
62090 case Kind of
62091 wcActive: Result := GTI.hwndActive;
62092 wcFocus: Result := GTI.hwndFocus;
62093 wcCapture: Result := GTI.hwndCapture;
62094 wcMenuOwner: Result := GTI.hwndMenuOwner;
62095 wcMoveSize: Result := GTI.hwndMoveSize;
62096 wcCaret: Result := GTI.hwndCaret;
62097 end;
62098 end;
62099 end;
62101 //[function GetFocusedChild]
62102 function GetFocusedChild( Wnd: HWnd ): HWnd;
62103 var Tr1, Tr2: THandle;
62104 begin
62105 Result := 0;
62106 Tr1 := GetCurrentThreadId;
62107 Tr2 := GetWindowThreadProcessId( Wnd, nil );
62108 if Tr1 = Tr2 then
62109 Result := GetFocus
62110 else
62111 if AttachThreadInput( Tr2, Tr1, True ) then
62112 begin
62113 Result := GetFocus;
62114 AttachThreadInput( Tr2, Tr1, False );
62115 end;
62116 end;
62118 //[function WaitFocusedWndChild]
62119 function WaitFocusedWndChild( Wnd: HWnd ): HWnd;
62120 var T1, T2: Integer;
62121 W: HWnd;
62122 begin
62123 Sleep( 50 );
62124 T1 := GetTickCount;
62125 while True do
62126 begin
62127 W := GetTopWindow( Wnd );
62128 if W = 0 then W := Wnd;
62129 W := GetFocusedChild( W );
62130 if W <> 0 then
62131 begin
62132 Wnd := W;
62133 break;
62134 end;
62135 T2 := GetTickCount;
62136 if Abs( T1 - T2 ) > 100 then break;
62137 end;
62138 Result := Wnd;
62139 end;
62141 //[function Stroke2Window]
62142 function Stroke2Window( Wnd: HWnd; const S: String ): Boolean;
62143 var P: PChar;
62144 begin
62145 Result := False;
62146 //Wnd := GetTopWindow( Wnd );
62147 Wnd := WaitFocusedWndChild( Wnd );
62148 if Wnd = 0 then Exit;
62149 P := PChar( S );
62150 while P^ <> #0 do
62151 begin
62152 PostMessage( Wnd, WM_CHAR, Integer( P^ ), 1 );
62153 Inc( P );
62154 end;
62155 Result := True;
62156 end;
62158 //[function Stroke2WindowEx]
62159 function Stroke2WindowEx( Wnd: HWnd; const S: String; Wait: Boolean ): Boolean;
62160 var P: PChar;
62161 EndChar: Char;
62162 MsgDn, MsgUp, SCA: Integer;
62164 function Compare( Pattern: PChar ): Boolean;
62165 var Pos: PChar;
62166 C1, C2: Char;
62167 begin
62168 Pos := P;
62169 while Pattern^ <> #0 do
62170 begin
62171 C1 := Pattern^;
62172 C2 := Pos^;
62173 if C1 in [ 'a'..'z' ] then
62174 C1 := Char( Ord( C1 ) - $20 );
62175 if C2 in [ 'a'..'z' ] then
62176 C2 := Char( Ord( C2 ) - $20 );
62177 if C1 <> C2 then
62178 begin
62179 Result := False;
62180 Exit;
62181 end;
62182 Inc( Pos );
62183 Inc( Pattern );
62184 end;
62185 while Pos^ = ' ' do Inc( Pos );
62186 P := Pos;
62187 Result := True;
62188 end;
62190 procedure Send( Msg, KeyCode: Integer );
62191 var lParam: Integer;
62192 begin
62193 Wnd := WaitFocusedWndChild( Wnd );
62194 if Wnd = 0 then Exit;
62195 lParam := 1;
62196 if longBool( SCA and 4 ) then
62197 lParam := $20000001;
62198 if Msg = MsgUp then
62199 lParam := lParam or Integer($D0000000);
62200 PostMessage( Wnd, Msg, KeyCode, lParam );
62201 Applet.ProcessMessages;
62202 if Wait then
62203 Sleep( 50 );
62204 end;
62206 function CompareSend( Pattern: PChar; Value2Send: Integer ): Boolean;
62207 begin
62208 if Compare( Pattern ) then
62209 begin
62210 Send( MsgDn, Value2Send );
62211 Send( MsgUp, Value2Send );
62212 Result := True;
62214 else
62215 Result := False;
62216 end;
62218 function ParseKeys( EndChar: Char ): PChar;
62219 var FN: Integer;
62220 begin
62221 SCA := 0;
62222 while not (P^ in [ #0, EndChar ]) do
62223 begin
62224 if Compare( 'Shift' ) then SCA := SCA or 1
62225 else
62226 if Compare( 'Ctrl' ) then SCA := SCA or 2
62227 else
62228 if Compare( 'Alt' ) then SCA := SCA or 4
62229 else
62230 break;
62231 end;
62232 MsgDn := WM_KEYDOWN;
62233 MsgUp := WM_KEYUP;
62234 if LongBool( SCA and 4 ) then
62235 begin
62236 MsgDn := WM_SYSKEYDOWN;
62237 MsgUp := WM_SYSKEYUP;
62238 keybd_event( VK_MENU, 0, 0, 0 );
62239 Send( WM_SYSKEYDOWN, VK_MENU );
62240 end;
62241 if LongBool( SCA and 2 ) then
62242 begin
62243 keybd_event( VK_CONTROL, 0, 0, 0 );
62244 Send( WM_KEYDOWN, VK_CONTROL );
62245 end;
62246 if Longbool( SCA and 1 ) then
62247 begin
62248 keybd_event( VK_SHIFT, 0, 0, 0 );
62249 Send( WM_KEYDOWN, VK_SHIFT );
62250 end;
62251 while not (P^ in [ #0, EndChar ]) do
62252 begin
62253 if (P^ = 'F') and (P[ 1 ] in [ '1'..'9' ]) then
62254 begin
62255 Inc( P );
62256 FN := Ord( P^ ) - Ord( '0' );
62257 if (FN = 1) and (P[ 1 ] in [ '0'..'2' ]) then
62258 begin
62259 Inc( P );
62260 FN := 10 + Ord( P^ ) - Ord( '0' );
62261 end;
62262 repeat Inc( P ) until P^ <> ' ';
62263 FN := FN + $6F;
62264 Send( MsgDn, FN );
62265 Send( MsgUp, FN );
62267 else
62268 if Compare( 'Numpad' ) then
62269 begin
62270 if P^ in [ '0'..'9' ] then
62271 begin
62272 FN := Ord( P^ ) - Ord( '0' ) + $60;
62273 repeat Inc( P^ ) until P^ <> ' ';
62274 Send( MsgDn, FN );
62275 Send( MsgUp, FN );
62276 end;
62278 else
62279 if not (CompareSend( 'Add', $6B ) or
62280 CompareSend( 'Gray+', $6B ) or
62281 CompareSend( 'Apps', $5D ) or
62282 CompareSend( 'BackSpace', $08 ) or
62283 CompareSend( 'BkSp', $08 ) or
62284 CompareSend( 'BS', $08 ) or
62285 CompareSend( 'Break', $13 ) or
62286 CompareSend( 'CapsLock', $14 ) or
62287 CompareSend( 'Clear', $0C ) or
62288 CompareSend( 'Decimal', $6E ) or
62289 CompareSend( 'Del', $2E ) or
62290 CompareSend( 'Delete', $2E ) or
62291 CompareSend( 'Divide', $6F ) or
62292 CompareSend( 'Gray/', $6F ) or
62293 CompareSend( 'Down', $28 ) or
62294 CompareSend( 'End', $23 ) or
62295 CompareSend( 'Enter', $0D ) or
62296 CompareSend( 'Return', $0D ) or
62297 CompareSend( 'CR', $0D ) or
62298 CompareSend( 'Esc', $1B ) or
62299 CompareSend( 'Escape', $1B ) or
62300 CompareSend( 'Help', $2F ) or
62301 CompareSend( 'Home', $24 ) or
62302 CompareSend( 'Ins', $2D ) or
62303 CompareSend( 'Insert', $2D ) or
62304 CompareSend( 'Left', $25 ) or
62305 CompareSend( 'LWin', $5B ) or
62306 CompareSend( 'Multiply', $6A ) or
62307 CompareSend( 'Gray*', $6A ) or
62308 CompareSend( 'NumLock', $90 ) or
62309 CompareSend( 'PgDn', $22 ) or
62310 CompareSend( 'PgUp', $21 ) or
62311 CompareSend( 'PrintScrn', $2C ) or
62312 CompareSend( 'Right', $27 ) or
62313 CompareSend( 'RWin', $5C ) or
62314 CompareSend( 'Separator', $6C ) or
62315 CompareSend( 'ScrollLock', $91 ) or
62316 CompareSend( 'Subtract', $6D ) or
62317 CompareSend( 'Tab', $09 ) or
62318 CompareSend( 'Gray-', $6D ) or
62319 CompareSend( 'Up', $26 )) then break;
62320 end;
62321 while not (P^ in [ #0, EndChar ]) do
62322 begin
62323 if P^ in [ 'A'..'Z', '0'..'9' ] then
62324 begin
62325 Send( MsgDn, Integer( P^ ) );
62326 Send( MsgUp, Integer( P^ ) );
62328 else
62329 if P^ in [ #1..#255 ] then
62330 Stroke2Window( Wnd, '' + P^ );
62331 repeat Inc( P ) until (P^ <> ' ');
62332 end;
62333 if P^ = EndChar then
62334 Inc( P );
62335 if Longbool( SCA and 1 ) then
62336 begin
62337 Send( WM_KEYUP, VK_SHIFT );
62338 keybd_event( VK_SHIFT, 0, KEYEVENTF_KEYUP, 0 );
62339 end;
62340 if LongBool( SCA and 2 ) then
62341 begin
62342 Send( WM_KEYUP, VK_CONTROL );
62343 keybd_event( VK_CONTROL, 0, KEYEVENTF_KEYUP, 0 );
62344 end;
62345 if LongBool( SCA and 4 ) then
62346 begin
62347 Send( WM_SYSKEYUP, VK_MENU );
62348 keybd_event( VK_MENU, 0, KEYEVENTF_KEYUP, 0 );
62349 end;
62350 Result := P;
62351 end;
62353 begin
62354 Result := False;
62355 Wnd := GetTopWindow( Wnd );
62356 Wnd := GetFocusedChild( Wnd );
62357 if Wnd = 0 then Exit;
62358 P := PChar( S );
62359 while P^ <> #0 do
62360 begin
62361 if not (P^ in [ '[', '{' ]) then
62362 begin
62363 Stroke2Window( Wnd, '' + P^ );
62364 Inc( P );
62366 else
62367 begin
62368 if P^ = '[' then
62369 EndChar := ']'
62370 else
62371 EndChar := '}';
62372 Inc( P );
62373 P := ParseKeys( EndChar );
62374 end;
62375 end;
62376 Result := True;
62377 end;
62379 type
62380 PHWnd = ^HWnd;
62382 TFindWndRec = packed Record
62383 ThreadID : DWord;
62384 WndFound : HWnd;
62385 end;
62386 PFindWndRec = ^TFindWndRec;
62388 //[function EnumWindowsProc]
62389 function EnumWindowsProc( Wnd : HWnd; Find : PFindWndRec ) : Boolean;
62390 stdcall;
62391 var Id : DWord;
62392 begin
62393 Result := True;
62394 Id := GetWindowThreadProcessId( Wnd, @Id );
62395 if Id = Find.ThreadID then
62396 begin
62397 Find.WndFound := Wnd;
62398 Result := False;
62399 end;
62400 end;
62402 //[function FindWindowByThreadID]
62403 function FindWindowByThreadID( ThreadID : DWORD ) : HWnd;
62404 var Find : TFindWndRec;
62405 begin
62406 Find.ThreadID := ThreadID;
62407 Find.WndFound := 0;
62408 EnumWindows( @EnumWindowsProc, Integer( @Find ) );
62409 Result := Find.WndFound;
62410 end;
62412 //[function GetDesktopRect]
62413 function GetDesktopRect : TRect;
62414 var W1, W2 : HWnd;
62415 begin
62416 Result := MakeRect( 0, 0, GetSystemMetrics( SM_CXSCREEN ), GetSystemMetrics( SM_CYSCREEN ) );
62417 W2 := findwindow(nil,'Program Manager');
62418 W1 := findwindowex(W2,0,'SHELLDLL_DefView',nil);
62419 if W1 = 0 then Exit;
62420 GetWindowRect( W1, Result );
62421 end;
62423 //[function GetWorkArea]
62424 function GetWorkArea: TRect;
62425 begin
62426 SystemParametersInfo( SPI_GETWORKAREA, 0, @ Result, 0 );
62427 end;
62429 //[function ExecuteWait]
62430 function ExecuteWait( const AppPath, CmdLine, DfltDirectory: String;
62431 Show: DWORD; TimeOut: DWORD; ProcID: PDWORD ): Boolean;
62432 var Flags: DWORD;
62433 Startup: TStartupInfo;
62434 ProcInf: TProcessInformation;
62435 DfltDir: PChar;
62436 App: String;
62437 begin
62438 Result := FALSE;
62439 Flags := CREATE_NEW_CONSOLE;
62440 if Show = SW_HIDE then
62441 Flags := Flags or {$IFDEF F_P}$08000000{$ELSE}CREATE_NO_WINDOW{$ENDIF};
62442 FillChar( Startup, SizeOf( Startup ), 0 );
62443 Startup.cb := Sizeof( Startup );
62444 Startup.wShowWindow := Show;
62445 Startup.dwFlags := STARTF_USESHOWWINDOW;
62446 if ProcID <> nil then
62447 ProcID^ := 0;
62448 DfltDir := nil;
62449 if DfltDirectory <> '' then
62450 DfltDir := PChar( DfltDirectory );
62451 if ProcID <> nil then
62452 ProcID^ := 0;
62453 App := AppPath;
62454 if (pos( ' ', App ) > 0) and (pos( '"', App ) <= 0) then
62455 App := '"' + App + '"';
62456 if (App <> '') and (CmdLine <> '') then
62457 App := App + ' ';
62458 if CreateProcess( nil, PChar( App + CmdLine ), nil,
62459 nil, FALSE, Flags, nil, DfltDir, Startup,
62460 ProcInf ) then
62461 begin
62462 if WaitForSingleObject( ProcInf.hProcess, TimeOut ) = WAIT_OBJECT_0 then
62463 begin
62464 CloseHandle( ProcInf.hProcess );
62465 Result := TRUE;
62467 else
62468 begin
62469 if ProcID <> nil then
62470 ProcID^ := ProcInf.hProcess;
62471 end;
62472 CloseHandle( ProcInf.hThread );
62473 end;
62474 end;
62476 //[function ExecuteIORedirect]
62477 function ExecuteIORedirect( const AppPath, CmdLine, DfltDirectory: String;
62478 Show: DWORD; ProcID: PDWORD; InPipe, OutPipeWr, OutPipeRd: PHandle ): Boolean;
62479 var Flags: DWORD;
62480 Startup: TStartupInfo;
62481 ProcInf: TProcessInformation;
62482 DfltDir: PChar;
62483 SecurityAttributes: TSecurityAttributes;
62484 SaveStdOut, SaveStdIn: THandle;
62485 ChildStdOutRd, ChildStdOutWr: THandle;
62486 ChildStdInRd, ChildStdInWr: THandle;
62487 ChildStdOutRdDup: THandle;
62488 ChildStdInWrDup: THandle;
62490 procedure Do_CloseHandle( var Handle: THandle );
62491 begin
62492 if Handle <> 0 then
62493 begin
62494 CloseHandle( Handle );
62495 Handle := 0;
62496 end;
62497 end;
62499 procedure Close_Handles;
62500 begin
62501 Do_CloseHandle( ChildStdOutRd );
62502 Do_CloseHandle( ChildStdOutWr );
62503 Do_CloseHandle( ChildStdInRd );
62504 Do_CloseHandle( ChildStdInWr );
62505 end;
62507 function RedirectInputOutput: Boolean;
62508 begin
62509 Result := FALSE;
62510 if (OutPipeRd <> nil) or (OutPipeWr <> nil) then
62511 begin
62512 // redirect output
62513 SaveStdOut := GetStdHandle(STD_OUTPUT_HANDLE);
62514 if not CreatePipe( ChildStdOutRd, ChildStdOutWr, @ SecurityAttributes, 0 ) then
62515 Exit;
62516 if not SetStdHandle( STD_OUTPUT_HANDLE, ChildStdOutWr ) then
62517 Exit;
62518 if not DuplicateHandle( GetCurrentProcess, ChildStdOutRd,
62519 GetCurrentProcess, @ ChildStdOutRdDup, 0, FALSE,
62520 2 {DUPLICATE_SAME_ACCESS} ) then
62521 Exit;
62522 Do_CloseHandle( ChildStdOutRd );
62523 if OutPipeRd <> nil then
62524 OutPipeRd^ := ChildStdOutRdDup;
62525 if OutPipeWr <> nil then
62526 OutPipeWr^ := ChildStdOutWr;
62527 end;
62528 if InPipe <> nil then
62529 begin
62530 // redirect input
62531 SaveStdIn := GetStdHandle(STD_INPUT_HANDLE);
62532 if not CreatePipe( ChildStdInRd, ChildStdInWr, @ SecurityAttributes, 0 ) then
62533 Exit;
62534 if not SetStdHandle( STD_INPUT_HANDLE, ChildStdInRd ) then
62535 Exit;
62536 if not DuplicateHandle( GetCurrentProcess, ChildStdInWr,
62537 GetCurrentProcess, @ ChildStdInWrDup, 0, FALSE,
62538 2 {DUPLICATE_SAME_ACCESS} ) then
62539 Exit;
62540 Do_CloseHandle( ChildStdInWr );
62541 if InPipe <> nil then
62542 InPipe^ := ChildStdInWrDup;
62543 Do_CloseHandle( ChildStdInRd );
62544 end;
62545 Result := TRUE;
62546 end;
62548 procedure Restore_Saved_StdInOut;
62549 begin
62550 //if SaveStdOut <> 0 then
62551 SetStdHandle( STD_OUTPUT_HANDLE, SaveStdOut );
62552 //if SaveStdin <> 0 then
62553 SetStdHandle( STD_INPUT_HANDLE, SaveStdIn );
62554 end;
62556 begin
62557 Result := FALSE;
62558 Flags := 0;
62559 if Show = SW_HIDE then
62560 Flags := Flags or {$IFDEF F_P}$08000000{$ELSE}CREATE_NO_WINDOW{$ENDIF};
62561 FillChar( Startup, SizeOf( Startup ), 0 );
62562 Startup.cb := Sizeof( Startup );
62563 {Startup.wShowWindow := Show;
62564 Startup.dwFlags := STARTF_USESHOWWINDOW;}
62565 if ProcID <> nil then
62566 ProcID^ := 0;
62567 DfltDir := nil;
62568 SecurityAttributes.nLength := Sizeof( SecurityAttributes );
62569 SecurityAttributes.lpSecurityDescriptor := nil;
62570 SecurityAttributes.bInheritHandle := TRUE;
62571 SaveStdOut := 0;
62572 SaveStdIn := 0;
62573 ChildStdOutRd := 0;
62574 ChildStdOutWr := 0;
62575 ChildStdInRd := 0;
62576 ChildStdInWr := 0;
62577 if not RedirectInputOutput then
62578 begin
62579 Close_Handles;
62580 Exit;
62581 end;;
62582 if DfltDirectory <> '' then
62583 DfltDir := PChar( DfltDirectory );
62584 if CreateProcess( nil, PChar( '"' + AppPath + '" ' + CmdLine ),
62585 nil, nil, TRUE, Flags, nil, DfltDir, Startup,
62586 ProcInf ) then
62587 begin
62588 if ProcID <> nil then
62589 ProcID^ := ProcInf.hProcess
62590 else
62591 CloseHandle( ProcInf.hProcess );
62592 CloseHandle( ProcInf.hThread );
62593 Restore_Saved_StdInOut;
62594 Result := TRUE;
62596 else
62597 begin
62598 Restore_Saved_StdInOut;
62599 Close_Handles;
62600 Exit;
62601 end;
62602 end;
62604 //[function ExecuteConsoleAppIORedirect]
62605 function ExecuteConsoleAppIORedirect( const AppPath, CmdLine, DfltDirectory: String;
62606 Show: DWORD; const InStr: String; var OutStr: String; WaitTimeout: DWORD ): Boolean;
62607 var PipeIn, PipeOutRd, PipeOutWr: THandle;
62608 ProcID: DWORD;
62609 BytesCount: DWORD;
62610 Buffer: array[ 0..4096 ] of Char;
62611 BufStr: String;
62612 PPipeIn: PHandle;
62613 begin
62614 Result := FALSE;
62615 PPipeIn := @ PipeIn;
62616 if InStr = '' then
62617 PPipeIn := nil;
62618 PipeOutRd := 0;
62619 PipeOutWr := 0;
62620 if not ExecuteIORedirect( AppPath, CmdLine, DfltDirectory, Show, @ ProcID,
62621 PPipeIn, @ PipeOutWr, @ PipeOutRd ) then Exit;
62622 if PPipeIn <> nil then
62623 begin
62624 if InStr <> '' then
62625 WriteFile( PipeIn, InStr[ 1 ], Length( InStr ), BytesCount, nil );
62626 CloseHandle( PipeIn );
62627 end;
62628 OutStr := '';
62629 if WaitForSingleObject( ProcID, WaitTimeOut ) = WAIT_OBJECT_0 then
62630 begin
62631 CloseHandle( ProcID );
62632 CloseHandle( PipeOutWr );
62633 while ReadFile( PipeOutRd, Buffer, Sizeof( Buffer ), BytesCount, nil ) do
62634 begin
62635 SetLength( BufStr, BytesCount );
62636 Move( Buffer[ 0 ], BufStr[ 1 ], BytesCount );
62637 OutStr := OutStr + BufStr;
62638 end;
62640 else
62641 CloseHandle( PipeOutWr );
62642 CloseHandle( PipeOutRd );
62643 Result := TRUE;
62644 end;
62646 {$IFDEF _D2}
62647 //[API OpenProcessToken]
62648 function OpenProcessToken(ProcessHandle: THandle; DesiredAccess: DWORD;
62649 var TokenHandle: THandle): BOOL; stdcall;
62650 external advapi32 name 'OpenProcessToken';
62651 {$ENDIF}
62653 //[function WindowsShutdown]
62654 function WindowsShutdown( const Machine : String; Force, Reboot : Boolean ) : Boolean;
62656 hToken: THandle;
62657 tkp, tkp_prev: TTokenPrivileges;
62658 dwRetLen :DWORD;
62659 Flags: Integer;
62660 begin
62661 Result := False;
62662 if Integer( GetVersion ) < 0 then // Windows95/98/Me
62663 begin
62664 if Machine <> '' then Exit;
62665 Flags := EWX_SHUTDOWN;
62666 if Reboot then
62667 Flags := Flags or EWX_REBOOT;
62668 if Force then
62669 Flags := Flags or EWX_FORCE;
62670 Result := ExitWindowsEx( Flags, 0 );
62671 Exit;
62672 end;
62674 OpenProcessToken(GetCurrentProcess(),
62675 TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,
62676 hToken);
62678 if not LookupPrivilegeValue(PChar(Machine),
62679 'SeShutdownPrivilege',tkp.Privileges[0].Luid)
62680 then
62681 Exit;
62683 tkp_prev:=tkp;
62684 tkp.PrivilegeCount:=1;
62685 tkp.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;
62686 AdjustTokenPrivileges(hToken, FALSE, tkp, sizeof(tkp), tkp_prev,
62687 dwRetLen);
62689 if not LookupPrivilegeValue(PChar(Machine),
62690 'SeRemoteShutdownPrivilege',
62691 tkp.Privileges[0].Luid)
62692 then
62693 Exit;
62695 tkp.PrivilegeCount:=1;
62696 tkp.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;
62697 AdjustTokenPrivileges(hToken, FALSE, tkp, sizeof(tkp), tkp_prev,
62698 dwRetLen);
62700 Result := InitiateSystemShutdown(PChar(Machine),nil, 0, Force, Reboot);
62701 end;
62703 var SaveWinVer: Byte = $FF;
62705 //[function WinVer]
62706 function WinVer : TWindowsVersion;
62707 {* Returns Windows version. }
62708 var OVI: TOsVersionInfo;
62709 begin
62710 if SaveWinVer <> $FF then Result := TWindowsVersion( SaveWinVer )
62711 else
62712 begin
62713 OVI.dwOSVersionInfoSize := Sizeof( OVI );
62714 GetVersionEx( OVI );
62715 with OVI do
62716 if dwPlatformId = VER_PLATFORM_WIN32_NT then
62717 begin
62718 Result := wvNT;
62719 if dwMajorVersion >= 6 then
62720 Result := wvLongHorn
62721 else begin
62722 if dwMajorVersion >= 5 then
62723 if dwMinorVersion >=1 then
62724 Result := wvXP
62725 else
62726 Result := wvY2K;
62727 end;
62729 {if dwPlatformId = VER_PLATFORM_WIN32_NT then
62730 begin
62731 Result := wvNT;
62732 if dwMajorVersion >= 5 then
62733 Result := wvY2K;
62734 end}
62735 else
62736 if dwPlatformId = VER_PLATFORM_WIN32_WINDOWS then
62737 begin
62738 Result := wv95;
62739 if (dwMajorVersion > 4) or (dwMajorVersion = 4)
62740 and (dwMinorVersion >= 10) then
62741 Result := wv98;
62743 else
62744 Result := wv31; // Windows 3.1 (WIN32s)
62745 SaveWinVer := Ord( Result );
62746 end;
62747 end;
62749 //[function IsWinVer]
62750 function IsWinVer( Ver : TWindowsVersions ) : Boolean;
62751 {* Returns True if Windows version is in given range of values. }
62752 begin
62753 Result := WinVer in Ver;
62754 end;
62756 //[procedure TControl.SetAlphaBlend]
62757 procedure TControl.SetAlphaBlend(const Value: Integer);
62758 const
62759 LWA_COLORKEY=$00000001;
62760 LWA_ALPHA=$00000002;
62761 ULW_COLORKEY=$00000001;
62762 ULW_ALPHA=$00000002;
62763 ULW_OPAQUE=$00000004;
62764 WS_EX_LAYERED=$00080000;
62765 type
62766 TSetLayeredWindowAttributes=
62767 function( hwnd: Integer; crKey: TColor; bAlpha: Byte; dwFlags: DWORD )
62768 : Boolean; stdcall;
62770 SetLayeredWindowAttributes: TSetLayeredWindowAttributes;
62771 User32: THandle;
62772 dw: DWORD;
62773 begin
62774 if Value = fAlphaBlend then Exit;
62775 fAlphaBlend := Value;
62776 User32 := GetModuleHandle( 'User32' );
62777 SetLayeredWindowAttributes := GetProcAddress( User32,
62778 'SetLayeredWindowAttributes' );
62779 if Assigned( SetLayeredWindowAttributes ) then
62780 begin
62781 dw := GetWindowLong( GetWindowHandle, GWL_EXSTYLE );
62782 if Byte( Value ) < 255 then
62783 begin
62784 SetWindowLong( fHandle, GWL_EXSTYLE, dw or WS_EX_LAYERED );
62785 SetLayeredWindowAttributes( fHandle, 0, Value and $FF, LWA_ALPHA);
62787 else
62788 SetWindowLong( fHandle, GWL_EXSTYLE, dw and not WS_EX_LAYERED );
62789 end;
62790 end;
62792 //[function TControl.SetPosition]
62793 function TControl.SetPosition( X, Y: Integer ): PControl;
62794 begin
62795 Left := X;
62796 Top := Y;
62797 Result := @Self;
62798 end;
62800 //[function NewColorDialog]
62801 function NewColorDialog( FullOpen: TColorCustomOption ): PColorDialog;
62802 var I: Integer;
62803 begin
62805 New( Result, Create );
62806 {+}{++}(*Result := PColorDialog.Create;*){--}
62807 Result.ColorCustomOption := FullOpen;
62808 for I := 1 to 16 do
62809 Result.CustomColors[ I ] := clWhite;
62810 end;
62811 //[END NewColorDialog]
62813 { TColorDialog }
62815 //[function TColorDialog.Execute]
62816 function TColorDialog.Execute: Boolean;
62817 var CD: TChooseColor;
62818 begin
62819 CD.lStructSize := Sizeof( CD );
62820 CD.hWndOwner := OwnerWindow;
62821 //CD.hInstance := 0;
62822 CD.rgbResult := Color2RGB( Color );
62823 CD.lpCustColors := @CustomColors[ 1 ];
62824 CD.Flags := CC_RGBINIT;
62825 case ColorCustomOption of
62826 ccoFullOpen: CD.Flags := CD.Flags or CC_FULLOPEN;
62827 ccoPreventFullOpen: CD.Flags := CD.Flags or CC_PREVENTFULLOPEN;
62828 end;
62829 Result := ChooseColor( CD );
62830 if Result then
62831 Color := CD.rgbResult;
62832 end;
62834 //[procedure TControl.SetMaxProgress]
62835 procedure TControl.SetMaxProgress(const Index, Value: Integer);
62836 begin
62837 // ignore index, and set Value via PBM_SETRANGE32: ()
62838 Perform( PBM_SETRANGE32, 0, Value );
62839 end;
62841 //[procedure TControl.SetDroppedWidth]
62842 procedure TControl.SetDroppedWidth(const Value: Integer);
62843 begin
62844 FDroppedWidth := Value;
62845 Perform( CB_SETDROPPEDWIDTH, Value, 0 );
62846 end;
62848 //[function TControl.LVGetItemState]
62849 function TControl.LVGetItemState(Idx: Integer): TListViewItemState;
62850 type
62851 PListViewItemState = ^TListViewItemState;
62852 var I: Byte;
62853 begin
62854 I := Perform( LVM_GETITEMSTATE, Idx,
62855 LVIS_CUT or LVIS_DROPHILITED or LVIS_FOCUSED or LVIS_SELECTED );
62856 Result := PListViewItemState( @ I )^;
62857 end;
62859 //[procedure TControl.LVSetItemState]
62860 procedure TControl.LVSetItemState(Idx: Integer; const Value: TListViewItemState);
62861 var Data: TLVItem;
62862 begin
62863 //FillChar( Data, Sizeof( Data ), 0 );
62864 //Data.mask := LVIF_DI_SETITEM or LVIF_STATE;
62865 Data.stateMask := LVIS_FOCUSED or LVIS_SELECTED or LVIS_CUT or LVIS_DROPHILITED;
62866 Data.state := PByte( @ Value )^;
62867 //Data.iItem := Idx;
62868 Perform( LVM_SETITEMSTATE, Idx, Integer( @Data ) );
62869 end;
62871 //[procedure TControl.LVSelectAll]
62872 procedure TControl.LVSelectAll;
62873 begin
62874 LVSetItemState( -1, [ lvisSelect ] );
62875 end;
62877 //[function TControl.LVItemInsert]
62878 function TControl.LVItemInsert(Idx: Integer; const aText: String): Integer;
62879 var LVI: TLVItem;
62880 begin
62881 LVI.mask := LVIF_TEXT or LVIF_DI_SETITEM;
62882 LVI.iItem := Idx;
62883 LVI.iSubItem := 0;
62884 LVI.pszText := PChar( aText );
62885 Result := Perform( LVM_INSERTITEM, 0, Integer( @LVI ) );
62886 end;
62888 {$IFNDEF _FPC}
62889 {$IFNDEF _D2}
62890 //[function TControl.LVItemInsertW]
62891 function TControl.LVItemInsertW(Idx: Integer;
62892 const aText: WideString): Integer;
62893 var LVI: TLVItemW;
62894 begin
62895 LVI.mask := LVIF_TEXT or LVIF_DI_SETITEM;
62896 LVI.iItem := Idx;
62897 LVI.iSubItem := 0;
62898 LVI.pszText := PWideChar( aText );
62899 Result := Perform( LVM_INSERTITEMW, 0, Integer( @LVI ) );
62900 end;
62901 {$ENDIF _D2}
62902 {$ENDIF _FPC}
62904 //[function TControl.LVItemAdd]
62905 function TControl.LVItemAdd(const aText: String): Integer;
62906 begin
62907 Result := LVItemInsert( Count, aText );
62908 end;
62910 {$IFNDEF _FPC}
62911 {$IFNDEF _D2}
62912 //[function TControl.LVItemAddW]
62913 function TControl.LVItemAddW(const aText: WideString): Integer;
62914 begin
62915 Result := LVItemInsertW( Count, aText );
62916 end;
62917 {$ENDIF _D2}
62918 {$ENDIF _FPC}
62920 //[function TControl.LVGetSttImgIdx]
62921 function TControl.LVGetSttImgIdx(Idx: Integer): Integer;
62922 begin
62923 Result := Perform( LVM_GETITEMSTATE, Idx, LVIS_STATEIMAGEMASK ) shr 12;
62924 end;
62926 //[procedure TControl.LVSetSttImgIdx]
62927 procedure TControl.LVSetSttImgIdx(Idx: Integer; const Value: Integer);
62928 var LVI: TLVItem;
62929 begin
62930 LVI.stateMask := LVIS_STATEIMAGEMASK;
62931 LVI.state := Value shl 12;
62932 Perform( LVM_SETITEMSTATE, Idx, Integer( @LVI ) );
62933 end;
62935 //[function TControl.LVGetOvlImgIdx]
62936 function TControl.LVGetOvlImgIdx(Idx: Integer): Integer;
62937 begin
62938 Result := Perform( LVM_GETITEMSTATE, Idx, LVIS_OVERLAYMASK ) shr 8;
62939 end;
62941 //[procedure TControl.LVSetOvlImgIdx]
62942 procedure TControl.LVSetOvlImgIdx(Idx: Integer; const Value: Integer);
62943 var LVI: TLVItem;
62944 begin
62945 LVI.stateMask := LVIS_OVERLAYMASK;
62946 LVI.state := Value shl 8;
62947 Perform( LVM_SETITEMSTATE, Idx, Integer( @LVI ) );
62948 end;
62950 //[function TControl.LVGetItemData]
62951 function TControl.LVGetItemData(Idx: Integer): DWORD;
62952 var LVI: TLVItem;
62953 begin
62954 LVI.mask := LVIF_PARAM;
62955 LVI.iItem := Idx;
62956 LVI.iSubItem := 0;
62957 Perform( LVM_GETITEM, 0, Integer( @LVI ) );
62958 Result := LVI.lParam;
62959 end;
62961 //[procedure TControl.LVSetItemData]
62962 procedure TControl.LVSetItemData(Idx: Integer; const Value: DWORD);
62963 var LVI: TLVItem;
62964 begin
62965 LVI.mask := LVIF_PARAM;
62966 LVI.iItem := Idx;
62967 LVI.iSubItem := 0;
62968 LVI.lParam := Value;
62969 Perform( LVM_SETITEM, 0, Integer( @LVI ) );
62970 end;
62972 //[function TControl.LVGetItemIndent]
62973 function TControl.LVGetItemIndent(Idx: Integer): Integer;
62974 var LI: TLVItem;
62975 begin
62976 LI.mask := LVIF_INDENT;
62977 LI.iItem := Idx;
62978 LI.iSubItem := 0;
62979 Perform( LVM_GETITEM, 0, Integer( @LI ) );
62980 Result := LI.iIndent;
62981 end;
62983 //[procedure TControl.LVSetItemIndent]
62984 procedure TControl.LVSetItemIndent(Idx: Integer; const Value: Integer);
62985 var LI: TLVItem;
62986 begin
62987 LI.mask := LVIF_INDENT or LVIF_DI_SETITEM;
62988 LI.iItem := Idx;
62989 LI.iSubItem := 0;
62990 LI.iIndent := Value;
62991 Perform( LVM_SETITEM, 0, Integer( @LI ) );
62992 end;
62994 type
62995 TNMLISTVIEW = packed Record
62996 hdr: TNMHDR;
62997 iItem: Integer;
62998 iSubItem: Integer;
62999 uNewState: Integer;
63000 uOldState: Integer;
63001 uChanged: Integer;
63002 ptAction: Integer;
63003 lParam: DWORD;
63004 end;
63005 PNMLISTVIEW = ^TNMLISTVIEW;
63007 //[function WndProc_LVDeleteItem]
63008 function WndProc_LVDeleteItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer )
63009 : Boolean;
63010 var Hdr: PNMHDR;
63011 LV: PNMListView;
63012 begin
63013 Result := FALSE;
63014 if Msg.message = WM_NOTIFY then
63015 begin
63016 Hdr := Pointer(Msg.lParam);
63017 if Hdr.hwndFrom = Sender.Handle then
63018 begin
63019 LV := Pointer( Hdr );
63020 if Hdr.code = LVN_DELETEITEM then
63021 begin
63022 if Assigned( Sender.OnDeleteLVItem ) then
63023 Sender.OnDeleteLVItem( Sender, LV.iItem );
63024 Result := TRUE;
63026 else
63027 if Hdr.code = LVN_DELETEALLITEMS then
63028 begin
63029 if Assigned( Sender.OnDeleteAllLVItems ) then
63030 begin
63031 Sender.OnDeleteAllLVItems( Sender );
63032 Rslt := 0;
63033 if Assigned( Sender.OnDeleteLVItem ) then
63034 Rslt := 1;
63035 end;
63036 Result := TRUE;
63037 end;
63038 end;
63039 end;
63040 end;
63042 //[procedure TControl.SetOnDeleteAllLVItems]
63043 procedure TControl.SetOnDeleteAllLVItems(const Value: TOnEvent);
63044 begin
63045 fOnDeleteAllLVItems := Value;
63046 AttachProc( @WndProc_LVDeleteItem );
63047 end;
63049 //[procedure TControl.SetOnDeleteLVItem]
63050 procedure TControl.SetOnDeleteLVItem(const Value: TOnDeleteLVItem);
63051 begin
63052 fOnDeleteLVItem := Value;
63053 AttachProc( @WndProc_LVDeleteItem );
63054 end;
63056 //[function WndProc_LVData]
63057 function WndProc_LVData( Sender: PControl; var Msg: TMsg; var Rslt: Integer )
63058 : Boolean;
63059 var Hdr: PNMHDR;
63060 DI: PLVDispInfo;
63061 Store: Boolean;
63062 Txt: String;
63063 LV: PControl;
63064 {$IFDEF UNICODE_CTRLS}
63065 TxtW: WideString;
63066 {$ENDIF UNICODE_CTRLS}
63067 begin
63068 Result := FALSE;
63069 if Msg.message = WM_NOTIFY then
63070 begin
63071 Hdr := Pointer(Msg.lParam);
63072 if Hdr.hwndFrom = Sender.Handle then
63073 begin
63074 if (Hdr.code = LVN_GETDISPINFO)
63075 {$IFDEF UNICODE_CTRLS}
63076 or (Hdr.code = LVN_GETDISPINFOW)
63077 {$ENDIF UNICODE_CTRLS}
63078 then
63079 begin
63080 DI := Pointer( Hdr );
63081 LV := Sender;
63082 if LV <> nil then
63083 begin
63084 Txt := '';
63085 DI.item.iImage := -1;
63086 DI.item.state := 0;
63087 Store := FALSE;
63088 if (Assigned( LV.OnLVData )
63089 {$IFDEF UNICODE_CTRLS}
63090 or Assigned( LV.OnLVDataW )
63091 {$ENDIF UNICODE_CTRLS}
63093 and (DI.item.iItem >= 0) then
63094 begin
63095 {$IFDEF UNICODE_CTRLS}
63096 TxtW := '';
63097 if Assigned( LV.ONLVDataW ) then
63098 LV.OnLVDataW( LV, DI.item.iItem, DI.item.iSubItem, TxtW,
63099 DI.item.iImage, DWORD( DI.item.state ), Store )
63100 else
63101 {$ENDIF UNICODE_CTRLS}
63102 LV.OnLVData( LV, DI.item.iItem, DI.item.iSubItem, Txt,
63103 DI.item.iImage, DWORD( DI.item.state ), Store );
63104 {$IFNDEF UNICODE_CTRLS}
63105 if (LV.fCaption = nil) or (Integer( StrLen( LV.fCaption ) ) <=
63106 Length( Txt ) ) then
63107 {$ENDIF UNICODE_CTRLS}
63108 begin
63109 if LV.fCaption <> nil then
63110 FreeMem( LV.fCaption );
63111 {$IFDEF UNICODE_CTRLS}
63112 GetMem( LV.fCaption, (Length( Txt ) + Length( TxtW ) + 1)
63113 * Sizeof( WideChar ) );
63114 {$ELSE NOT_UNICODE_CTRLS}
63115 GetMem( LV.fCaption, Length( Txt ) + 1 );
63116 {$ENDIF NOT_UNICODE_CTRLS}
63117 end;
63118 {$IFDEF UNICODE_CTRLS}
63119 PWord( @ LV.fCaption[ 0 ] )^ := 0;
63120 {$ELSE}
63121 LV.fCaption[ 0 ] := #0;
63122 {$ENDIF}
63123 if Txt {$IFDEF UNICODE_CTRLS} + TxtW {$ENDIF UNICODE_CTRLS}
63124 <> '' then
63125 begin
63126 {$IFDEF UNICODE_CTRLS}
63127 if Hdr.code = LVN_GETDISPINFOW then
63128 begin
63129 if Txt <> '' then
63130 TxtW := Txt;
63131 Move( TxtW[ 1 ], LV.fCaption[ 0 ], (Length( TxtW ) + 1) * Sizeof( WideChar ) );
63132 end else
63133 {$ENDIF UNICODE_CTRLS}
63134 StrCopy( LV.fCaption, @Txt[ 1 ] );
63135 end;
63136 DI.item.pszText := LV.fCaption;
63137 if Store then
63138 DI.item.mask := DI.item.mask or LVIF_DI_SETITEM;
63139 end;
63140 Result := TRUE;
63141 end;
63142 end;
63143 end;
63144 end;
63145 end;
63147 //[procedure TControl.SetOnLVData]
63148 procedure TControl.SetOnLVData(const Value: TOnLVData);
63149 begin
63150 fOnLVData := Value;
63151 AttachProc( @WndProc_LVData );
63152 Perform( LVM_SETCALLBACKMASK, LVIS_OVERLAYMASK or LVIS_STATEIMAGEMASK, 0 );
63153 end;
63155 {$IFNDEF _FPC}
63156 {$IFNDEF _D2}
63157 //[procedure TControl.SetOnLVDataW]
63158 procedure TControl.SetOnLVDataW(const Value: TOnLVDataW);
63159 begin
63160 fOnLVDataW := Value;
63161 AttachProc( @WndProc_LVData );
63162 Perform( LVM_SETCALLBACKMASK, LVIS_OVERLAYMASK or LVIS_STATEIMAGEMASK, 0 );
63163 end;
63164 {$ENDIF _D2}
63165 {$ENDIF _FPC}
63167 //[function WndProc_LVCustomDraw]
63168 function WndProc_LVCustomDraw( Sender: PControl; var Msg: TMsg;
63169 var Rslt: Integer ): Boolean;
63170 var NMCustDraw: PNMLVCustomDraw;
63171 NMHdr: PNMHdr;
63172 ItemIdx, SubItemIdx: Integer;
63173 S: TListViewItemState;
63174 ItemState: TDrawState;
63175 begin
63176 Result := FALSE;
63177 if Msg.message = WM_NOTIFY then
63178 begin
63179 NMHdr := Pointer( Msg.lParam );
63180 if (NMHdr.code = NM_CUSTOMDRAW) and Assigned( Sender.fOnLVCustomDraw ) then
63181 begin
63182 NMCustDraw := Pointer( Msg.lParam );
63183 ItemIdx := -1;
63184 SubItemIdx := -1;
63185 if LongBool( NMCustDraw.nmcd.dwDrawStage and CDDS_ITEM ) then
63186 ItemIdx := NMCustDraw.nmcd.dwItemSpec;
63187 if LongBool( NMCustDraw.nmcd.dwDrawStage and CDDS_SUBITEM ) then
63188 SubItemIdx := NMCustDraw.iSubItem;
63189 ItemState := [ ];
63190 if ItemIdx >= 0 then
63191 begin
63192 S := Sender.LVItemState[ ItemIdx ];
63193 if lvisFocus in S then
63194 ItemState := ItemState + [ odsFocused ];
63195 if lvisSelect in S then
63196 ItemState := ItemState + [ odsSelected ];
63197 if lvisBlend in S then
63198 ItemState := ItemState + [ odsGrayed ];
63199 if lvisHighlight in S then
63200 ItemState := ItemState + [ odsMarked ];
63201 end;
63203 Sender.Canvas;
63205 Rslt := Sender.FOnLVCustomDraw( Sender, {Sender.Canvas.Handle} NMCustDraw.nmcd.hdc,
63206 NMCustDraw.nmcd.dwDrawStage, ItemIdx, SubItemIdx, NMCustDraw.nmcd.rc,
63207 ItemState, TColor( NMCustDraw.clrText ), TColor( NMCustDraw.clrTextBk ) );
63209 Result := TRUE;
63210 end;
63211 end;
63212 end;
63214 //[procedure TControl.SetOnLVCustomDraw]
63215 procedure TControl.SetOnLVCustomDraw(const Value: TOnLVCustomDraw);
63216 begin
63217 fOnLVCustomDraw := Value;
63218 AttachProc( @WndProc_LVCustomDraw );
63219 end;
63221 //[function CompareLVItems]
63222 function CompareLVItems( Idx1, Idx2: Integer; ListView: PControl ): Integer; stdcall;
63223 begin
63224 if Assigned( ListView.fOnCompareLVItems ) then
63225 Result := ListView.fOnCompareLVItems( ListView, Idx1, Idx2 )
63226 else
63227 Result := 0;
63228 end;
63230 //[procedure TControl.LVSort]
63231 procedure TControl.LVSort;
63232 begin
63233 Perform( LVM_SORTITEMSEX, Integer(@Self), Integer(@CompareLVItems) );
63234 end;
63236 //[function CompareLVItemsData]
63237 function CompareLVItemsData( D1, D2: DWORD; ListView: PControl ): Integer; stdcall;
63238 begin
63239 if Assigned( ListView.fOnCompareLVItems ) then
63240 Result := ListView.fOnCompareLVItems( ListView, D1, D2 )
63241 else
63242 Result := 0;
63243 end;
63245 //[procedure TControl.LVSortData]
63246 procedure TControl.LVSortData;
63247 begin
63248 Perform( LVM_SORTITEMS, Integer( @Self ), Integer( @CompareLVItemsData ) );
63249 end;
63251 //[function WndProc_LVColumnClick]
63252 function WndProc_LVColumnClick( Sender: PControl; var Msg: TMsg; var Rslt: Integer )
63253 : Boolean;
63254 var Hdr: PNMHDR;
63255 LV: PNMListView;
63256 begin
63257 Result := FALSE;
63258 if Msg.message = WM_NOTIFY then
63259 begin
63260 Hdr := Pointer(Msg.lParam);
63261 if Hdr.hwndFrom = Sender.Handle then
63262 begin
63263 LV := Pointer( Hdr );
63264 if Hdr.code = LVN_COLUMNCLICK then
63265 begin
63266 if Assigned( Sender.OnColumnClick ) then
63267 Sender.OnColumnClick( Sender, LV.iSubItem );
63268 Result := TRUE;
63269 end;
63270 end;
63271 end;
63272 end;
63274 //[procedure TControl.SetOnColumnClick]
63275 procedure TControl.SetOnColumnClick(const Value: TOnLVColumnClick);
63276 begin
63277 fOnColumnClick := Value;
63278 AttachProc( @WndProc_LVColumnClick );
63279 end;
63281 //[function WndProc_LVStateChange]
63282 function WndProc_LVStateChange( Sender: PControl; var Msg: TMsg; var R: Integer ): Boolean;
63283 var NMOD: PNMLVODStateChange;
63284 NMLV: PNMLISTVIEW;
63285 begin
63286 if Msg.message = WM_NOTIFY then
63287 begin
63288 NMOD := Pointer( Msg.lParam );
63289 NMLV := Pointer( Msg.lParam );
63290 if NMOD.hdr.code = LVN_ODSTATECHANGED then
63291 begin
63292 if Assigned( Sender.OnLVStateChange ) then
63293 Sender.OnLVStateChange( Sender, NMOD.iFrom, NMOD.iTo,
63294 NMOD.uOldState, NMOD.uNewState );
63296 else
63297 if NMLV.hdr.code = LVN_ITEMCHANGED then
63298 begin
63299 if Assigned( Sender.OnLVStateChange ) then
63300 Sender.OnLVStateChange( Sender, NMLV.iItem, NMLV.iItem,
63301 NMLV.uOldState, NMLV.uNewState );
63302 end;
63303 end;
63304 Result := FALSE;
63305 end;
63307 //[procedure TControl.SetOnLVStateChange]
63308 procedure TControl.SetOnLVStateChange(const Value: TOnLVStateChange);
63309 begin
63310 FOnLVStateChange := Value;
63311 AttachProc( WndProc_LVStateChange );
63312 end;
63314 //[function WndProc_LVDelete]
63315 function WndProc_LVDelete( Sender: PControl; var Msg: TMsg; var R: Integer ): Boolean;
63316 var NMLV: PNMLISTVIEW;
63317 begin
63318 if Msg.message = WM_NOTIFY then
63319 begin
63320 NMLV := Pointer( Msg.lParam );
63321 if NMLV.hdr.code = LVN_DELETEITEM then
63322 begin
63323 if Assigned( Sender.OnLVDelete ) then
63324 Sender.OnLVDelete( Sender, NMLV.iItem );
63325 end;
63326 end;
63327 Result := FALSE;
63328 end;
63330 //[procedure TControl.SetOnLVDelete]
63331 procedure TControl.SetOnLVDelete(const Value: TOnLVDelete);
63332 begin
63333 FOnLVDelete := Value;
63334 Add2AutoFreeEx( Clear );
63335 AttachProcEx( WndProc_LVDelete, TRUE );
63336 if fParent <> nil then
63337 begin
63338 fParent.DetachProc( WndProcNotify );
63339 fParent.AttachProcEx( WndProcNotify, TRUE );
63340 end;
63341 end;
63343 //[function CompareLVColumns]
63344 function CompareLVColumns( Idx1, Idx2: Integer; Sender: PControl ): Integer; stdcall;
63345 var S1, S2: String;
63346 begin
63347 //--- changed by Mike Gerasimov:
63348 S1 := Sender.LVItems[ Idx1, Sender.fColumn ];
63349 S2 := Sender.LVItems[ Idx2, Sender.fColumn ];
63350 If lvoSortAscending in Sender.fLVOptions Then
63351 Result := AnsiCompareStrNoCase( S1, S2 )
63352 Else
63353 If lvoSortDescending in Sender.fLVOptions Then
63354 Result := AnsiCompareStrNoCase( S2, S1 )
63355 Else
63356 Result:=0;
63357 end;
63359 //[procedure TControl.LVSortColumn]
63360 procedure TControl.LVSortColumn(Idx: Integer);
63361 begin
63362 fColumn := Idx;
63363 Perform( LVM_SORTITEMSEX, Integer(@Self), Integer(@CompareLVColumns) );
63364 end;
63366 //[function TControl.LVIndexOf]
63367 function TControl.LVIndexOf(const S: String): Integer;
63368 begin
63369 Result := LVSearchFor( S, -1, FALSE );
63370 end;
63372 {$IFNDEF _FPC}
63373 {$IFNDEF _D2}
63374 //[function TControl.LVIndexOfW]
63375 function TControl.LVIndexOfW(const S: WideString): Integer;
63376 begin
63377 Result := LVSearchForW( S, -1, FALSE );
63378 end;
63379 {$ENDIF _D2}
63380 {$ENDIF _FPC}
63382 //[function TControl.LVSearchFor]
63383 function TControl.LVSearchFor(const S: String; StartAfter: Integer;
63384 Partial: Boolean): Integer;
63385 var f: TLVFindInfo;
63386 begin
63387 f.lParam := 0;
63388 f.flags := LVFI_STRING;
63389 if Partial then
63390 f.flags := LVFI_STRING or LVFI_PARTIAL;
63391 f.psz := @s[1];
63392 result := Perform(LVM_FINDITEM,StartAfter,integer(@f));
63393 end;
63395 {$IFNDEF _FPC}
63396 {$IFNDEF _D2}
63397 //[function TControl.LVSearchForW]
63398 function TControl.LVSearchForW(const S: WideString; StartAfter: Integer;
63399 Partial: Boolean): Integer;
63400 var f: TLVFindInfoW;
63401 begin
63402 f.lParam := 0;
63403 f.flags := LVFI_STRING;
63404 if Partial then
63405 f.flags := LVFI_STRING or LVFI_PARTIAL;
63406 f.psz := @s[1];
63407 result := Perform(LVM_FINDITEMW,StartAfter,integer(@f));
63408 end;
63409 {$ENDIF _D2}
63410 {$ENDIF _FPC}
63412 function WndProcLVMeasureItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
63413 const
63414 ClsName: PChar = 'obj_SysListView32'#0;
63416 pMI: PMeasureItemStruct;
63417 pLV: PControl;
63418 H: Integer;
63419 wnd: HWND;
63420 wId: DWORD;
63422 begin
63424 Result := FALSE;
63425 if Msg.message = WM_MEASUREITEM then begin
63426 pMI := Pointer(Msg.lParam);
63427 with pMI^ do begin
63428 if CtlType=ODT_LISTVIEW then begin
63429 wnd := 0;
63431 repeat
63432 wnd := FindWindowEx(Sender.GetWindowHandle,wnd,ClsName,nil);
63433 wId := GetWindowLong(wnd,GWL_ID);
63434 if CtlID = wId then begin
63435 pLV := Pointer(GetProp(wnd,ID_SELF));
63436 if pLV <> nil then begin
63437 H := pLV.Perform(WM_MEASUREITEM,0,0);
63438 if H > 0 then begin
63439 itemHeight := H;
63440 Rslt:=1;
63441 Result := TRUE;
63442 end;
63443 break;
63444 end;
63445 end;
63446 until wnd = 0;
63448 end;
63449 end;
63450 end;
63451 end;
63453 function WndProcLVMeasureItem2( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
63454 begin
63455 Result := FALSE;
63456 if (Msg.message = WM_MEASUREITEM) and (Msg.wParam = 0) then begin
63457 Rslt := Sender.fLVItemHeight;
63458 Result := TRUE;
63459 end;
63461 end;
63463 function TControl.SetLVItemHeight(Value: Integer): PControl;
63464 begin
63465 Set_LVItemHeight( Value );
63466 Result := @ Self;
63467 end;
63469 procedure TControl.Set_LVItemHeight(Value: Integer);
63470 begin
63471 if fLVItemHeight <> Value then begin
63472 if fLVItemHeight = 0 then begin
63473 Parent.AttachProc(WndProcLVMeasureItem);
63474 AttachProc(WndProcLVMeasureItem2);
63475 end;
63476 fLVItemHeight := Value;
63477 end;
63478 end;
63480 //[function TControl.IndexOf]
63481 function TControl.IndexOf(const S: String): Integer;
63482 begin
63483 Result := SearchFor( S, -1, FALSE );
63484 end;
63486 //[function TControl.SearchFor]
63487 function TControl.SearchFor(const S: String; StartAfter: Integer;
63488 Partial: Boolean): Integer;
63489 var Cmd: Integer;
63490 I: Integer;
63491 begin
63492 Cmd := fCommandActions.aFindItem;
63493 if Partial then
63494 Cmd := fCommandActions.aFindPartial;
63495 if Cmd <> 0 then
63496 Result := Perform( Cmd, StartAfter, Integer( PChar( S ) ) )
63497 else
63498 begin
63499 Result := -1;
63500 for I := StartAfter+1 to Count-1 do
63501 begin
63502 if Partial and ( Copy( Items[ I ], 1, Length( S ) ) = S ) or
63503 ( Items[ I ] = S ) then
63504 begin
63505 Result := I;
63506 break;
63507 end;
63508 end;
63509 end;
63510 end;
63512 //[function TControl.DefaultBtnProc]
63513 function TControl.DefaultBtnProc(var Msg: TMsg;
63514 var Rslt: Integer): Boolean;
63515 var Btn: PControl;
63516 F: PControl;
63517 //Msg1: TMsg;
63518 begin
63519 if Assigned( fOldOnMessage ) then
63520 begin
63521 Result := fOldOnMessage( Msg, Rslt );
63522 if Result then Exit;
63523 end;
63524 Result := FALSE;
63525 if AppletTerminated then Exit;
63526 F := Applet;
63527 if not F.fIsForm then
63528 begin
63529 F := F.fCurrentControl;
63530 if F = nil then Exit;
63531 end;
63532 Btn := nil;
63533 if ((Msg.message = WM_KEYDOWN) or (Msg.message = WM_KEYUP)) and
63534 ((Msg.wParam = VK_RETURN) or (Msg.wParam = VK_ESCAPE)) then
63535 begin
63536 if (Msg.wParam = VK_RETURN) and
63537 (F.fDefaultBtnCtl <> nil) and
63538 F.fDefaultBtnCtl.ToBeVisible and
63539 F.fDefaultBtnCtl.Enabled and
63540 ((F.fCurrentControl=nil) or (not F.fCurrentControl.fCancelBtn and
63541 not F.fCurrentControl.fIgnoreDefault)
63542 or (F.fCurrentControl = F.fDefaultBtnCtl)
63543 ) then
63544 Btn := F.fDefaultBtnCtl
63545 else
63546 if (Msg.wParam = VK_ESCAPE) and
63547 (F.fCancelBtnCtl <> nil) and
63548 F.fCancelBtnCtl.ToBeVisible and
63549 F.fCancelBtnCtl.Enabled then
63550 Btn := F.fCancelBtnCtl
63551 else
63552 if (Msg.wParam = VK_RETURN) and
63553 (F.fAllBtnReturnClick or fAllBtnReturnClick) and
63554 (F.ActiveControl <> nil) and
63555 (F.ActiveControl.IsButton) and
63556 (F.ActiveControl.Count = 0) then
63557 Btn := F.ActiveControl;
63558 if Btn <> nil then
63559 begin
63560 if Msg.message = WM_KEYDOWN then
63561 Btn.Focused := TRUE;
63562 Btn.Perform( Msg.message, DWORD( ' ' ), Msg.lParam );
63563 Msg.wParam := 0;
63564 Result := TRUE;
63565 Rslt := 0;
63566 Exit;
63568 end;
63569 Result := FALSE;
63570 end;
63572 //[procedure TControl.SetDefaultBtn]
63573 procedure TControl.SetDefaultBtn(const Index: Integer;
63574 const Value: Boolean);
63575 var F, C: PControl;
63576 begin
63577 if Index = 13 then
63578 begin
63579 fDefaultBtn := Value;
63580 fCancelBtn := FALSE;
63582 else
63583 if Index = 27 then
63584 begin
63585 fCancelBtn := Value;
63586 fDefaultBtn := FALSE;
63587 end;
63588 if Applet = nil then Exit;
63589 F := ParentForm;
63590 if F <> nil then
63591 begin
63592 if Value then
63593 begin
63594 if @ Applet.fOnMessage <> @ TControl.DefaultBtnProc then
63595 Applet.fOldOnMessage := Applet.fOnMessage; // fixed by YS
63596 Applet.fOnMessage := Applet.DefaultBtnProc;
63598 else
63599 begin
63600 Applet.fOnMessage := Applet.fOldOnMessage;
63601 Applet.fOldOnMessage := nil;
63602 end;
63603 C := nil;
63604 if Value then C := @ Self;
63605 if Index = 13 then
63606 begin
63607 F.fDefaultBtnCtl := C;
63608 if Value then
63609 Style := Style or BS_DEFPUSHBUTTON
63610 else
63611 Style := Style and not BS_DEFPUSHBUTTON;
63613 else
63614 if Index = 27 then
63615 F.fCancelBtnCtl := C;
63616 end;
63617 end;
63619 {$IFDEF F_P}
63620 //[function TControl.GetDefaultBtn]
63621 function TControl.GetDefaultBtn(const Index: Integer): Boolean;
63622 begin
63623 CASE Index OF
63624 13: Result := fDefaultBtn;
63625 27: Result := fCancelBtn;
63626 END;
63627 end;
63628 {$ENDIF F_P}
63630 //[function TControl.AllBtnReturnClick]
63631 function TControl.AllBtnReturnClick: PControl;
63632 {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}
63633 begin
63634 // nothing: already implemented in WndProcBtnReturnClick
63635 Result := @ Self;
63636 end;
63637 {$ELSE}
63638 var F: PControl;
63639 begin
63640 SetDefaultBtn( 0, TRUE );
63641 F := ParentForm;
63642 if F <> nil then
63643 F.fAllBtnReturnClick := TRUE;
63644 Result := @ Self;
63645 end;
63646 {$ENDIF}
63648 //[function WndProc_CNDrawItem]
63649 function WndProc_CNDrawItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer )
63650 : Boolean;
63651 type PDrawAction = ^TDrawAction;
63652 PDrawState = ^TDrawState;
63653 var DI: PDrawItemStruct;
63654 begin
63655 Result := FALSE;
63656 if Msg.message = CN_DRAWITEM then
63657 begin
63658 DI := Pointer( Msg.lParam );
63659 if Assigned( Sender.OnDrawItem ) then
63660 begin
63661 if Sender.OnDrawItem( Sender, DI.hDC, DI.rcItem, DI.itemID,
63662 PDrawAction( @ DI.itemAction )^,
63663 PDrawState( @ DI.itemState )^ )
63664 then Rslt := 1
63665 else Rslt := 0;
63666 Result := TRUE;
63668 else Rslt := 0;
63669 end;
63670 end;
63672 //[procedure TControl.SetOnDrawItem]
63673 procedure TControl.SetOnDrawItem(const Value: TOnDrawItem);
63674 begin
63675 fOnDrawItem := Value;
63676 if Parent <> nil then
63677 Parent.AttachProc( @WndProc_DrawItem );
63678 AttachProc( @WndProc_CNDrawItem );
63679 end;
63681 //[function WndProc_MeasureItem]
63682 function WndProc_MeasureItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer )
63683 : Boolean;
63684 var MI: PMeasureItemStruct;
63685 Control: PControl;
63686 I: Integer;
63687 begin
63688 Result := FALSE;
63689 if Msg.message = WM_MEASUREITEM then
63690 begin
63691 MI := Pointer( Msg.lParam );
63692 for I := 0 to Sender.ChildCount - 1 do
63693 begin
63694 Control := Sender.Children[ I ];
63695 if Control.Menu = MI.CtlID then
63696 begin
63697 if Assigned( Control.OnMeasureItem ) then
63698 begin
63699 MI.itemHeight := Control.OnMeasureItem( Control, MI.itemID );
63700 if MI.itemHeight > 0 then
63701 begin
63702 Rslt := 1;
63703 Result := TRUE;
63704 end;
63705 end;
63706 break;
63707 end;
63708 end;
63709 end;
63710 end;
63712 //[procedure TControl.SetOnMeasureItem]
63713 procedure TControl.SetOnMeasureItem(const Value: TOnMeasureItem);
63714 begin
63715 fOnMeasureItem := Value;
63716 if Parent <> nil then
63717 Parent.AttachProc( @WndProc_MeasureItem );
63718 end;
63720 //[function TControl.GetItemData]
63721 function TControl.GetItemData(Idx: Integer): DWORD;
63722 begin
63723 Result := 0;
63724 if fCommandActions.aGetItemData <> 0 then
63725 Result := Perform( fCommandActions.aGetItemData, Idx, 0 );
63726 end;
63728 //[procedure TControl.SetItemData]
63729 procedure TControl.SetItemData(Idx: Integer; const Value: DWORD);
63730 begin
63731 if fCommandActions.aSetItemData <> 0 then
63732 Perform( fCommandActions.aSetItemData, Idx, Value );
63733 end;
63735 //[function TControl.GetLVCurItem]
63736 function TControl.GetLVCurItem: Integer;
63737 begin
63738 Result := Perform( LVM_GETNEXTITEM, -1, LVNI_SELECTED );
63739 end;
63741 //[procedure TControl.SetLVCurItem]
63742 procedure TControl.SetLVCurItem(const Value: Integer);
63743 begin
63744 if (lvoMultiselect in LVOptions) or (Value <> LVCurItem ) then
63745 LVItemState[ -1 ] := [ ];
63746 if Value >= 0 then
63747 LVItemState[ Value ] := [ lvisSelect, lvisFocus ];
63748 end;
63750 //[function TControl.LVNextItem]
63751 function TControl.LVNextItem(IdxPrev: Integer; Attrs: DWORD): Integer;
63752 begin
63753 Result := Perform( LVM_GETNEXTITEM, IdxPrev, Attrs );
63754 end;
63756 //[function TControl.LVNextSelected]
63757 function TControl.LVNextSelected(IdxPrev: Integer): Integer;
63758 begin
63759 Result := Perform( LVM_GETNEXTITEM, IdxPrev, LVNI_SELECTED );
63760 end;
63762 //[procedure TControl.Close]
63763 procedure TControl.Close;
63764 begin
63765 PostMessage( Handle, WM_CLOSE, 0, 0 );
63766 end;
63768 //[function WndProcMinimize]
63769 function WndProcMinimize( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
63770 var Wnd: PControl;
63771 begin
63772 Result := FALSE;
63773 if (Msg.message = WM_SYSCOMMAND) and ((Msg.wParam and $FFF0) = SC_MINIMIZE)then
63774 begin
63775 if Applet <> nil then
63776 begin
63777 Wnd := Applet.FMinimizeWnd;
63778 if Wnd <> nil then
63779 SetWindowPos( Applet.Handle, 0, Wnd.Left, Wnd.Top, Wnd.Width, 0,
63780 SWP_NOZORDER or SWP_NOREDRAW);
63781 end;
63782 end;
63783 end;
63785 //[procedure TControl.MinimizeNormalAnimated]
63786 procedure TControl.MinimizeNormalAnimated;
63787 var App: PControl;
63788 begin
63789 App := Applet;
63790 if App = nil then
63791 App := @Self;
63792 App.FMinimizeWnd := @Self;
63793 App.AttachProc( @WndProcMinimize );
63794 end;
63796 //[function WndProcDropFiles]
63797 function WndProcDropFiles( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
63798 var hDrop: THandle;
63799 Pt: TPoint;
63800 FList: String;
63801 I, N: Integer;
63802 Buf: array[ 0..MAX_PATH ] of Char;
63803 begin
63804 if Msg.message = WM_DROPFILES then
63805 if Assigned( Sender.FOnDropFiles ) then
63806 begin
63807 hDrop := Msg.wParam;
63808 DragQueryPoint( hDrop, Pt );
63809 N := DragQueryFile( hDrop, $FFFFffff, nil, 0 );
63810 FList := '';
63811 for I := 0 to N-1 do
63812 begin
63813 if FList <> '' then
63814 FList := FList + #13;
63815 DragQueryFile( hDrop, I, Buf, Sizeof( Buf ) );
63816 FList := FList + Buf;
63817 end;
63818 DragFinish( hDrop );
63819 Sender.FOnDropFiles( Sender, FList, Pt );
63820 Rslt := 0;
63821 Result := TRUE;
63822 Exit;
63823 end;
63824 Result := FALSE;
63825 end;
63827 //[procedure TControl.SetOnDropFiles]
63828 procedure TControl.SetOnDropFiles(const Value: TOnDropFiles);
63829 begin
63830 FOnDropFiles := Value;
63831 AttachProc( @WndProcDropFiles );
63832 DragAcceptFiles( GetWindowHandle, Assigned( Value ) );
63833 end;
63835 //[function WndProcShowHide]
63836 function WndProcShowHide( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
63837 var IsVisible: Boolean;
63838 begin
63839 if Msg.message = WM_SHOWWINDOW then
63840 if Msg.hwnd = Sender.Handle then
63841 begin
63842 IsVisible := IsWindowVisible( Sender.Handle );
63843 if LongBool( Msg.wParam ) then
63844 begin
63845 Sender.fVisible := TRUE;
63846 if not IsVisible then
63847 if Assigned( Sender.FOnShow ) then
63848 Sender.FOnShow( Sender );
63850 else
63851 begin
63852 Sender.fVisible := FALSE;
63853 if IsVisible then
63854 if Assigned( Sender.FOnHide ) then
63855 Sender.FOnHide( Sender );
63856 end;
63857 end;
63858 Result := FALSE;
63859 end;
63861 //[procedure TControl.SetOnHide]
63862 procedure TControl.SetOnHide(const Value: TOnEvent);
63863 begin
63864 FOnHide := Value;
63865 AttachProc( WndProcShowHide );
63866 end;
63868 //[procedure TControl.SetOnShow]
63869 procedure TControl.SetOnShow(const Value: TOnEvent);
63870 begin
63871 FOnShow := Value;
63872 AttachProc( WndProcShowHide );
63873 end;
63875 //[function TControl.BringToFront]
63876 function TControl.BringToFront: PControl;
63877 begin
63878 SetWindowPos( GetWindowHandle, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOMOVE or
63879 SWP_NOACTIVATE or SWP_NOOWNERZORDER or SWP_SHOWWINDOW );
63880 Result := @Self;
63881 end;
63883 //[function TControl.SendToBack]
63884 function TControl.SendToBack: PControl;
63885 begin
63886 SetWindowPos( GetWindowHandle, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOMOVE or
63887 SWP_NOACTIVATE or SWP_NOOWNERZORDER );
63888 Result := @Self;
63889 end;
63891 //[procedure TControl.DragStart]
63892 procedure TControl.DragStart;
63893 begin
63894 PostMessage( GetWindowHandle, WM_SYSCOMMAND, $F012, 0 );
63895 end;
63897 //[function WndProcDragWindow]
63898 function WndProcDragWindow( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
63899 var P: TPoint;
63900 begin
63901 if Msg.message = WM_MOUSEMOVE then
63902 begin
63903 if Sender.FDragging then
63904 begin
63905 GetCursorPos( P );
63906 P.x := P.x - Sender.fMouseStartPos.x + Sender.fDragStartPos.x;
63907 P.y := P.y - Sender.fMouseStartPos.y + Sender.fDragStartPos.y;
63908 Sender.Position := P;
63909 end;
63910 end;
63911 Result := FALSE;
63912 end;
63914 //[procedure TControl.DragStartEx]
63915 procedure TControl.DragStartEx;
63916 var StartBounds: TRect;
63917 begin
63918 GetCursorPos( fMouseStartPos );
63919 StartBounds := BoundsRect;
63920 fDragStartPos.x := StartBounds.Left;
63921 fDragStartPos.y := StartBounds.Top;
63922 SetCapture( GetWindowHandle );
63923 fDragging := TRUE;
63924 AttachProc( WndProcDragWindow );
63925 end;
63927 //[procedure TControl.DragStopEx]
63928 procedure TControl.DragStopEx;
63929 begin
63930 if FDragging then
63931 begin
63932 ReleaseCapture;
63933 FDragging := FALSE;
63934 end;
63935 end;
63937 //[function CallDragCallBack]
63938 function CallDragCallBack( Sender: PControl; var Stop: Boolean ): Boolean;
63939 var P: TPoint;
63940 Shape, ShapeWas: Integer;
63941 begin
63942 GetCursorPos( P );
63943 Shape := LoadCursor( 0, IDC_HAND );
63944 ShapeWas := Shape;
63945 Result := Sender.fDragCallback( Sender, P.x, P.y, Shape, Stop );
63946 if not Stop then
63947 begin
63948 if not Result then
63949 if Shape = ShapeWas then
63950 Shape := LoadCursor( 0, IDC_NO );
63951 ScreenCursor := Shape;
63953 else
63954 begin
63955 ScreenCursor := 0;
63956 Shape := Sender.fCursor;
63957 end;
63958 Windows.SetCursor( Shape );
63959 end;
63961 //[function WndProcDrag]
63962 function WndProcDrag( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
63963 var Stop: Boolean;
63964 begin
63965 if Sender.fDragging then
63966 begin
63967 Stop := FALSE;
63968 case Msg.message of
63969 WM_MOUSEMOVE:
63970 CallDragCallBack( Sender, Stop );
63971 WM_LBUTTONUP, WM_RBUTTONUP:
63972 begin
63973 Stop := TRUE;
63974 CallDragCallBack( Sender, Stop );
63975 end;
63976 else
63977 begin
63978 Result := FALSE;
63979 Exit;
63980 end;
63981 end;
63982 if Stop then
63983 begin
63984 ReleaseCapture;
63985 Sender.fDragging := FALSE;
63987 else
63988 begin
63989 Result := TRUE;
63990 exit;
63991 end;
63992 end;
63993 Result := FALSE;
63994 end;
63996 //[procedure TControl.DragItem]
63997 procedure TControl.DragItem(OnDrag: TOnDrag);
63998 begin
63999 fDragCallback := OnDrag;
64000 fDragging := TRUE;
64001 SetCapture( GetWindowHandle );
64002 AttachProc( WndProcDrag );
64003 end;
64006 {$IFDEF USE_CONSTRUCTORS} //****************************************************//
64008 //[constructor TControl.CreateWindowed]
64009 constructor TControl.CreateWindowed(AParent: PControl; AClassName: PChar; //
64010 ACtl3D: Boolean); //
64011 begin //
64012 CreateParented( AParent ); //
64013 fOnDynHandlers := WndProcDummy; //
64014 fWndProcKeybd := WndProcDummy; //
64015 fWndProcResizeFlicks := WndProcDummy; //
64016 fCommandActions.aClear := ClearText; //
64017 fWindowed := True; //
64018 fControlClassName := AClassName; //
64020 fControlClick := DummyObjProc; //
64022 fColor := clBtnFace; //
64023 fTextColor := clWindowText; //
64024 fMargin := 2; //
64025 fCtl3D := True; //
64026 fCtl3Dchild := True; //
64027 if AParent <> nil then //
64028 begin //
64029 fWndProcResizeFlicks := AParent.fWndProcResizeFlicks; //
64030 fGotoControl := AParent.fGotoControl; //
64031 fDoubleBuffered := AParent.fDoubleBuffered; //
64032 fTransparent := AParent.fTransparent; //
64033 fCtl3Dchild := AParent.fCtl3Dchild; //
64034 if AParent.fCtl3Dchild then //
64035 fCtl3D := ACtl3D //
64036 else //
64037 fCtl3D := False; //
64038 fMargin := AParent.fMargin; //
64039 with fBoundsRect do //
64040 begin //
64041 Left := AParent.fMargin + AParent.fClientLeft; //
64042 Top := AParent.fMargin + AParent.fClientTop; //
64043 Right := Left + 64; //
64044 Bottom := Top + 64; //
64045 end; //
64046 fTextColor := AParent.fTextColor; //
64047 fFont := fFont.Assign( AParent.fFont ); //
64048 if fFont <> nil then //
64049 begin //
64050 fFont.fOnChange := FontChanged; //
64051 FontChanged( fFont ); //
64052 end; //
64053 fColor := AParent.fColor; //
64054 fBrush := fBrush.Assign( AParent.fBrush ); //
64055 if fBrush <> nil then //
64056 begin //
64057 fBrush.fOnChange := BrushChanged; //
64058 BrushChanged( fBrush ); //
64059 end; //
64060 end; //
64061 end; //
64063 //[constructor TControl.CreateApplet]
64064 constructor TControl.CreateApplet(const ACaption: String); //
64065 begin //
64066 AppButtonUsed := True; //
64067 CreateWindowed( nil, 'App', TRUE ); //
64068 FIsApplet := TRUE; //
64069 fStyle := WS_VISIBLE or WS_SYSMENU or WS_POPUP or WS_MINIMIZEBOX //
64070 or WS_CAPTION; //
64071 fExStyle := WS_EX_APPWINDOW; //
64072 FCreateWndExt := CreateAppButton; //
64073 AttachProc( WndProcApp ); //
64074 Caption := ACaption; //
64075 end; //
64077 //[constructor TControl.CreateForm]
64078 constructor TControl.CreateForm(AParent: PControl; const ACaption: String); //
64079 begin //
64080 CreateWindowed( AParent, 'Form', TRUE ); //
64081 AttachProc( WndProcForm ); //
64082 AttachProc( WndProcDoEraseBkgnd ); //
64083 Caption := ACaption; //
64084 end; //
64086 //[constructor TControl.CreateControl]
64087 constructor TControl.CreateControl(AParent: PControl; AClassName: PChar; //
64088 AStyle: DWORD; ACtl3D: Boolean; Actions: PCommandActions); //
64089 var Form: PControl; //
64090 begin //
64091 CreateWindowed( AParent, AClassName, ACtl3D ); //
64092 if Actions <> nil then //
64093 fCommandActions := Actions^; //
64094 fIsControl := True; //
64095 fStyle := AStyle or WS_CLIPSIBLINGS or WS_CLIPCHILDREN; //
64096 fVisible := (Style and WS_VISIBLE) <> 0; //
64097 fTabstop := (Style and WS_TABSTOP) <> 0; //
64098 if (AParent <> nil) then //
64099 begin //
64100 Inc( AParent.ParentForm.fTabOrder ); //
64101 fTabOrder := AParent.ParentForm.fTabOrder; //
64102 end; //
64103 fLookTabKeys := [ tkTab, tkLeftRight, tkUpDown, tkPageUpPageDn ]; //
64104 if fCtl3D then //
64105 begin //
64106 fStyle := fStyle and not WS_BORDER; //
64107 fExStyle := fExStyle or WS_EX_CLIENTEDGE; //
64108 end; //
64109 if (Style and WS_TABSTOP) <> 0 then //
64110 begin //
64111 Form := ParentForm; //
64112 if Form <> nil then //
64113 if Form.FCurrentControl = nil then //
64114 Form.FCurrentControl := @Self; //
64115 end; //
64116 //fCreateParamsExt := CreateParams2; //
64117 fMenu := CtlIdCount; //
64118 Inc( CtlIdCount ); //
64119 AttachProc( WndProcCtrl ); //
64120 end; //
64122 //[constructor TControl.CreateButton]
64123 constructor TControl.CreateButton(AParent: PControl; //
64124 const ACaption: String); //
64125 begin //
64126 CreateControl( AParent, 'BUTTON', //
64127 WS_VISIBLE or WS_CHILD or //
64128 BS_PUSHLIKE or WS_TABSTOP, False, @ButtonActions ); //
64129 with fBoundsRect do //
64130 Bottom := Top + 22; //
64131 fTextAlign := taCenter; //
64132 Caption := ACaption; //
64133 end; //
64135 //[constructor TControl.CreateBitBtn]
64136 constructor TControl.CreateBitBtn(AParent: PControl; //
64137 const ACaption: String; AOptions: TBitBtnOptions; ALayout: TGlyphLayout; //
64138 AGlyphBitmap: HBitmap; AGlyphCount: Integer); //
64139 var //
64140 B: TBitmapInfo; //
64141 W, H: Integer; //
64142 begin //
64143 CreateControl( AParent, 'BUTTON', WS_VISIBLE or WS_CHILD or //
64144 WS_TABSTOP or BS_OWNERDRAW, False, @ButtonActions ); //
64145 fBitBtnOptions := AOptions; //
64146 fGlyphLayout := ALayout; //
64147 fGlyphBitmap := AGlyphBitmap; //
64148 with fBoundsRect do //
64149 begin //
64150 Bottom := Top + 22; //
64151 W := 0; H := 0; //
64152 if AGlyphBitmap <> 0 then //
64153 begin //
64154 if bboImageList in AOptions then //
64155 ImageList_GetIconSize( AGlyphBitmap, W, H ) //
64156 else //
64157 begin //
64158 if GetObject( AGlyphBitmap, Sizeof(B), @B ) > 0 then //
64159 begin //
64160 W := B.bmiHeader.biWidth; //
64161 H := B.bmiHeader.biHeight; //
64162 if AGlyphCount = 0 then //
64163 AGlyphCount := W div H; //
64164 if AGlyphCount > 1 then //
64165 W := W div AGlyphCount; //
64166 end; //
64167 end; //
64168 if W > 0 then //
64169 if ACaption = '' then //
64170 Right := Left + W //
64171 else //
64172 Right := Right + W; //
64173 if H > 0 then //
64174 Bottom := Top + H; //
64175 if not ( bboNoBorder in AOptions ) then //
64176 begin //
64177 if W > 0 then //
64178 Inc( Right, 2 ); //
64179 if H > 0 then //
64180 Inc( Bottom, 2 ); //
64181 end; //
64182 end; //
64183 fGlyphWidth := W; //
64184 fGlyphHeight := H; //
64185 end; //
64186 fGlyphCount := AGlyphCount; //
64187 if AParent <> nil then //
64188 AParent.AttachProc( WndProc_DrawItem ); //
64189 AttachProc( WndProcBitBtn ); //
64190 fTextAlign := taCenter; //
64191 Caption := ACaption; //
64192 end; //
64194 //[constructor TControl.CreateLabel]
64195 constructor TControl.CreateLabel(AParent: PControl; //
64196 const ACaption: String); //
64197 begin //
64198 CreateControl( AParent, 'STATIC', WS_VISIBLE or WS_CHILD or //
64199 SS_LEFTNOWORDWRAP or SS_NOPREFIX or SS_NOTIFY, //
64200 False, @LabelActions ); //
64201 fIsStaticControl := True; //
64202 fSizeRedraw := True; //
64203 fBoundsRect.Bottom := fBoundsRect.Top + 22; //
64204 Caption := ACaption; //
64205 end; //
64207 //[constructor TControl.CreateWordWrapLabel]
64208 constructor TControl.CreateWordWrapLabel(AParent: PControl; //
64209 const ACaption: String); //
64210 begin //
64211 CreateLabel( AParent, ACaption ); //
64212 fBoundsRect.Bottom := fBoundsRect.Top + 44; //
64213 fStyle := fStyle and not SS_LEFTNOWORDWRAP; //
64214 end; //
64216 //[constructor TControl.CreateLabelEffect]
64217 constructor TControl.CreateLabelEffect(AParent: PControl; ACaption: String; //
64218 AShadowDeep: Integer); //
64219 begin //
64220 CreateLabel( AParent, ACaption ); //
64221 fIsStaticControl := False; //
64222 AttachProc( WndProcLabelEffect ); //
64223 fTextAlign := taCenter; //
64224 fTextColor := clBtnShadow; //
64225 fShadowDeep := AShadowDeep; //
64226 fIgnoreWndCaption := True; //
64227 with fBoundsRect do //
64228 begin //
64229 Bottom := Top + 40; //
64230 end; //
64231 end; //
64233 //[constructor TControl.CreatePaintBox]
64234 constructor TControl.CreatePaintBox(AParent: PControl); //
64235 begin //
64236 CreateLabel( AParent, '' ); //
64237 with fBoundsRect do //
64238 begin //
64239 Right := Left + 40; //
64240 Bottom := Top + 40; //
64241 end; //
64242 end; //
64244 {$IFDEF ASM_VERSION} //
64245 //[constructor TControl.CreateGradientPanel]
64246 constructor TControl.CreateGradientPanel(AParent: PControl; AColor1, //
64247 AColor2: TColor); //
64248 asm //cmd //opd //
64249 XOR EDX, EDX //
64250 PUSH EDX //
64251 CALL CreateLabel //
64252 MOV ECX, AColor1 //
64253 MOV [EAX].fColor1, ECX //
64254 MOV ECX, AColor2 //
64255 MOV [EAX].fColor2, ECX //
64256 MOV EDX, [EAX].fBoundsRect.Left //
64257 ADD EDX, 40 //
64258 MOV [EAX].fBoundsRect.Right, EDX //
64259 MOV EDX, [EAX].fBoundsRect.Top //
64260 ADD EDX, 40 //
64261 MOV [EAX].fBoundsRect.Bottom, EDX //
64262 PUSH EAX //
64263 MOV EDX, offset[ WndProcGradient ] //
64264 CALL AttachProc //
64265 POP EAX //
64266 end; //
64267 {$ELSE ASM_VERSION} //Pascal //
64268 constructor TControl.CreateGradientPanel(AParent: PControl; AColor1, //
64269 AColor2: TColor); //
64270 begin //
64271 CreateLabel( AParent, '' ); //
64272 AttachProc( WndProcGradient ); //
64273 fColor2 := AColor2; //
64274 fColor1 := AColor1; //
64275 with fBoundsRect do //
64276 begin //
64277 Right := Left + 40; //
64278 Bottom := Top + 40; //
64279 end; //
64280 end; //
64281 {$ENDIF ASM_VERSION} //
64283 //[constructor TControl.CreateGradientPanelEx]
64284 constructor TControl.CreateGradientPanelEx(AParent: PControl; AColor1, //
64285 AColor2: TColor; AStyle: TGradientStyle; ALayout: TGradientLayout); //
64286 begin //
64287 CreateLabel( AParent, '' ); //
64288 AttachProc( WndProcGradientEx ); //
64289 fColor2 := AColor2; //
64290 fColor1 := AColor1; //
64291 fGradientStyle := AStyle; //
64292 fGradientLayout := ALayout; //
64293 with fBoundsRect do //
64294 begin //
64295 Right := Left + 40; //
64296 Bottom := Top + 40; //
64297 end; //
64298 end; //
64300 //[constructor TControl.CreateGroupbox]
64301 constructor TControl.CreateGroupbox(AParent: PControl; //
64302 const ACaption: String); //
64303 begin //
64304 CreateButton( AParent, ACaption ); //
64305 with fBoundsRect do //
64306 begin //
64307 Right := Left + 100; //
64308 Bottom := Top + 100; //
64309 end; //
64310 fStyle := WS_VISIBLE or WS_CHILD or BS_GROUPBOX or WS_TABSTOP; //
64311 fClientTop := 22; //
64312 fClientLeft := 2; //
64313 fClientBottom := 2; //
64314 fClientRight := 2; //
64315 fTabstop := False; //
64316 //AttachProc( WndProcGroupBox ); //
64317 end; //
64319 //[constructor TControl.CreateCheckbox]
64320 constructor TControl.CreateCheckbox(AParent: PControl; //
64321 const ACaption: String); //
64322 begin //
64323 CreateButton( AParent, ACaption ); //
64324 with fBoundsRect do //
64325 begin //
64326 Right := Left + 72; //
64327 end; //
64328 fStyle := WS_VISIBLE or WS_CHILD or //
64329 BS_AUTOCHECKBOX or WS_TABSTOP; //
64330 end; //
64332 //[constructor TControl.CreateRadiobox]
64333 constructor TControl.CreateRadiobox(AParent: PControl; //
64334 const ACaption: String); //
64335 begin //
64336 CreateCheckbox( AParent, ACaption ); //
64337 fStyle := WS_VISIBLE or WS_CHILD or //
64338 BS_RADIOBUTTON or WS_TABSTOP or WS_GROUP; //
64339 fControlClick := ClickRadio; //
64340 if AParent <> nil then //
64341 begin //
64342 AParent.fRadioLast := fMenu; //
64343 if AParent.fRadio1st = 0 then //
64344 begin //
64345 AParent.fRadio1st := fMenu; //
64346 SetRadioChecked; //
64347 end; //
64348 end; //
64349 end; //
64351 //[constructor TControl.CreateEditbox]
64352 constructor TControl.CreateEditbox(AParent: PControl; //
64353 AOptions: TEditOptions); //
64354 var Flags: Integer; //
64355 begin //
64356 Flags := MakeFlags( @AOptions, EditFlags ); //
64357 if not(eoMultiline in AOptions) then //
64358 Flags := Flags and not(WS_HSCROLL or WS_VSCROLL); //
64359 CreateControl( AParent, 'EDIT', WS_VISIBLE or WS_CHILD or WS_TABSTOP //
64360 or WS_BORDER or Flags, True, @EditActions ); //
64361 //YS fCursor := LoadCursor( 0, IDC_IBEAM ); // //YS
64362 with fBoundsRect do //
64363 begin //
64364 Right := Left + 100; //
64365 Bottom := Top + 22; //
64366 if eoMultiline in AOptions then //
64367 begin //
64368 Right := Right + 100; //
64369 Bottom := Top + 200; //
64370 end; //
64371 end; //
64372 fColor := clWindow; //
64373 fLookTabKeys := [ tkTab, tkUpDown, tkPageUpPageDn ]; //
64374 if eoMultiline in AOptions then //
64375 fLookTabKeys := [ tkTab ]; //
64376 if eoWantTab in AOptions then //
64377 fLookTabKeys := fLookTabKeys - [ tkTab ]; //
64378 end; //
64380 //[constructor TControl.CreatePanel]
64381 constructor TControl.CreatePanel(AParent: PControl; AStyle: TEdgeStyle); //
64382 const Edgestyles: array[ TEdgeStyle ] of DWORD = ( WS_DLGFRAME, SS_SUNKEN, 0 ); //
64383 begin //
64384 CreateControl( AParent, 'STATIC', WS_VISIBLE or WS_CHILD or //
64385 SS_LEFTNOWORDWRAP or SS_NOPREFIX or SS_NOTIFY, False, //
64386 @LabelActions ); //
64387 with fBoundsRect do //
64388 begin //
64389 Right := Left + 100; //
64390 Bottom := Top + 100; //
64391 end; //
64392 Style := Style or Edgestyles[ AStyle ]; //
64393 ExStyle := ExStyle or WS_EX_CONTROLPARENT; //
64394 end; //
64396 //[constructor TControl.CreateSplitter]
64397 constructor TControl.CreateSplitter(AParent: PControl; AMinSizePrev, //
64398 AMinSizeNext: Integer; EdgeStyle: TEdgeStyle); //
64399 var PrevCtrl: PControl; //
64400 Sz0: Integer; //
64401 begin //
64402 CreatePanel( AParent, EdgeStyle ); //
64403 fSplitMinSize1 := AMinSizePrev; //
64404 fSplitMinSize2 := AMinSizeNext; //
64405 Sz0 := 4; //
64406 with fBoundsRect do //
64407 begin //
64408 Right := Left + Sz0; //
64409 Bottom := Top + Sz0; //
64410 end; //
64411 if AParent <> nil then //
64412 begin //
64413 if AParent.fChildren.fCount > 1 then //
64414 begin //
64415 PrevCtrl := AParent.fChildren.fItems[ AParent.fChildren.fCount - 2 ]; //
64416 case PrevCtrl.FAlign of //
64417 caLeft, caRight: //
64418 begin //
64419 fCursor := LoadCursor( 0, IDC_SIZEWE ); //
64420 end; //
64421 caTop, caBottom: //
64422 begin //
64423 fCursor := LoadCursor( 0, IDC_SIZENS ); //
64424 end; //
64425 end; //
64426 Align := PrevCtrl.FAlign; //
64427 end; //
64428 end; //
64429 AttachProc( WndProcSplitter ); //
64430 end; //
64432 //[constructor TControl.CreateListbox]
64433 constructor TControl.CreateListbox(AParent: PControl; //
64434 AOptions: TListOptions); //
64435 var Flags: Integer; //
64436 begin //
64437 Flags := MakeFlags( @AOptions, ListFlags ); //
64438 CreateControl( AParent, 'LISTBOX', WS_VISIBLE or WS_CHILD or WS_TABSTOP //
64439 or WS_BORDER or WS_VSCROLL //
64440 or LBS_NOTIFY or Flags, True, @ListActions ); //
64441 with fBoundsRect do //
64442 begin //
64443 Right := Right + 100; //
64444 Bottom := Top + 200; //
64445 end; //
64446 fColor := clWindow; //
64447 fLookTabKeys := [ tkTab, tkLeftRight ]; //
64448 end; //
64450 //[constructor TControl.CreateCombobox]
64451 constructor TControl.CreateCombobox(AParent: PControl; //
64452 AOptions: TComboOptions); //
64453 var Flags: Integer; //
64454 begin //
64455 Flags := MakeFlags( @AOptions, ComboFlags ); //
64456 CreateControl( AParent, 'COMBOBOX', //
64457 WS_VISIBLE or WS_CHILD or WS_VSCROLL or //
64458 CBS_DROPDOWN or CBS_HASSTRINGS or WS_TABSTOP or Flags, //
64459 True, @ComboActions ); //
64460 fCreateWndExt := CreateComboboxWnd; //
64461 fDropDownProc := ComboboxDropDown; //
64462 fClsStyle := fClsStyle or CS_DBLCLKS; //
64463 with fBoundsRect do //
64464 begin //
64465 Right := Left + 100; //
64466 Bottom := Top + 22; //
64467 end; //
64468 fColor := clWindow; //
64469 fLookTabKeys := [ tkTab ]; //
64470 if coReadOnly in AOptions then //
64471 fLookTabKeys := [ tkTab, tkLeftRight ]; //
64472 end; //
64474 //[constructor TControl.CreateCommonControl]
64475 constructor TControl.CreateCommonControl(AParent: PControl; //
64476 AClassName: PChar; AStyle: DWORD; ACtl3D: Boolean; //
64477 Actions: PCommandActions); //
64478 begin //
64479 {*************} DoInitCommonControls( ICC_WIN95_CLASSES ); //
64480 CreateControl( AParent, AClassName, AStyle, ACtl3D, Actions ); //
64481 fIsCommonControl := True; //
64482 if AParent <> nil then //
64483 begin //
64484 AttachProc( WndProcParentResize ); //
64485 AParent.AttachProc( WndProcResize ); //
64486 AttachProc( WndProcCommonNotify ); //
64487 AParent.AttachProc( WndProcNotify ); //
64488 end; //
64489 end; //
64491 //[constructor TControl.CreateRichEdit1]
64492 constructor TControl.CreateRichEdit1(AParent: PControl; //
64493 AOptions: TEditOptions); //
64494 var Flags, I: Integer; //
64495 begin //
64496 if FRichEditModule = 0 then //
64497 begin //
64498 for I := 0 to 2 do //
64499 begin //
64500 FRichEditModule := LoadLibrary( RichEditLibnames[ I ] ); //
64501 if FRichEditModule > HINSTANCE_ERROR then break; //
64502 RichEditClass := 'RichEdit'; //
64503 end; //
64504 if FRichEditModule <= HINSTANCE_ERROR then //
64505 FRichEditModule := 0; //
64506 end; //
64507 Flags := MakeFlags( @AOptions, RichEditFlags ); //
64508 CreateCommonControl( AParent, RichEditClass, WS_VISIBLE or WS_CHILD //
64509 or WS_TABSTOP or WS_BORDER or ES_MULTILINE or Flags, //
64510 True, @RichEditActions ); //
64512 AttachProc( WndProcRichEditNotify ); //
64513 fDoubleBuffered := False; //
64514 fCannotDoubleBuf := True; //
64515 with fBoundsRect do //
64516 begin //
64517 Right := Right + 100; //
64518 Bottom := Top + 200; //
64519 end; //
64520 fColor := clWindow; //
64521 fLookTabKeys := [ tkTab ]; //
64522 if eoWantTab in AOptions then //
64523 fLookTabKeys := [ ]; //
64524 Perform( EM_SETEVENTMASK, 0, //
64525 ENM_CHANGE or ENM_SELCHANGE or ENM_REQUESTRESIZE or //
64526 ENM_PROTECTED or $04000000 {ENM_LINK} ); //
64527 Perform( EM_SETBKGNDCOLOR, 0, Color2RGB(fColor)); //
64528 end; //
64531 //[constructor TControl.CreateRichEdit]
64532 constructor TControl.CreateRichEdit(AParent: PControl; //
64533 AOptions: TEditOptions); //
64534 var OldRichEditClass, OldRichEditLib: PChar; //
64535 begin //
64536 if OleInit then //
64537 begin //
64538 OldRichEditClass := RichEditClass; //
64539 RichEditClass := 'RichEdit20A'; //
64540 OldRichEditLib := RichEditLib; //
64541 RichEditLib := 'RICHED20.DLL'; //
64542 CreateRichEdit1( AParent, AOptions ); //
64543 fCharFmtDeltaSz := 24; //
64544 // sizeof( TCharFormat2 ) - sizeof( RichEdit.TCharFormat ); //
64545 fParaFmtDeltaSz := sizeof( TParaFormat2 ) - sizeof( RichEdit.TParaFormat ); //
64546 RichEditClass := OldRichEditClass; //
64547 RichEditLib := OldRichEditLib; //
64548 end //
64549 else //
64550 CreateRichEdit1( AParent, AOptions ); //
64551 end; //
64553 //[constructor TControl.CreateProgressbar]
64554 constructor TControl.CreateProgressbar(AParent: PControl); //
64555 const ProgressBarFlags: array[ TProgressbarOption ] of Integer = //
64556 (PBS_VERTICAL, PBS_SMOOTH ); //
64557 begin //
64558 CreateCommonControl( AParent, PROGRESS_CLASS, //
64559 WS_CHILD or WS_VISIBLE, True, nil ); //
64560 with fBoundsRect do //
64561 begin //
64562 Right := Left + 300; //
64563 Bottom := Top + 20; //
64564 end; //
64565 fMenu := 0; //
64566 fTextColor := clHighlight; //
64567 end; //
64569 //[constructor TControl.CreateProgressbarEx]
64570 constructor TControl.CreateProgressbarEx(AParent: PControl; //
64571 AOptions: TProgressbarOptions); //
64572 const ProgressBarFlags: array[ TProgressbarOption ] of Integer = //
64573 (PBS_VERTICAL, PBS_SMOOTH ); //
64574 begin //
64575 CreateProgressbar( AParent ); //
64576 fStyle := fStyle or DWORD( MakeFlags( @AOptions, ProgressBarFlags ) ); //
64577 end; //
64579 //[constructor TControl.CreateListView]
64580 constructor TControl.CreateListView(AParent: PControl; //
64581 AStyle: TListViewStyle; AOptions: TListViewOptions; AImageListSmall, //
64582 AImageListNormal, AImageListState: PImageList); //
64583 begin //
64584 CreateCommonControl( AParent, WC_LISTVIEW, ListViewStyles[ AStyle ] or //
64585 LVS_SHAREIMAGELISTS or WS_CHILD or WS_VISIBLE or WS_TABSTOP, //
64586 True, @ListViewActions ); //
64587 fLVOptions := AOptions; //
64588 fLVStyle := AStyle; //
64589 fCreateWndExt := ApplyImageLists2ListView; //
64590 with fBoundsRect do //
64591 begin //
64592 Right := Left + 200; //
64593 Bottom := Top + 150; //
64594 end; //
64595 ImageListSmall := AImageListSmall; //
64596 ImageListNormal := AImageListNormal; //
64597 ImageListState := AImageListState; //
64598 fLVTextBkColor := clWindow; //
64599 fLookTabKeys := [ tkTab ]; //
64600 end; //
64602 //[constructor TControl.CreateTreeView]
64603 constructor TControl.CreateTreeView(AParent: PControl; //
64604 AOptions: TTreeViewOptions; AImgListNormal, AImgListState: PImageList); //
64605 var Flags: Integer; //
64606 begin //
64607 Flags := MakeFlags( @AOptions, TreeViewFlags ); //
64608 CreateCommonControl( AParent, WC_TREEVIEW, Flags or WS_VISIBLE or //
64609 WS_CHILD or WS_TABSTOP, True, @TreeViewActions ); //
64610 fCreateWndExt := ApplyImageLists2Control; //
64611 fColor := clWindow; //
64612 AttachProc( WndProcTreeView ); //
64613 with fBoundsRect do //
64614 begin //
64615 Right := Left + 150; //
64616 Bottom := Top + 200; //
64617 end; //
64618 ImageListNormal := AImgListNormal; //
64619 ImageListState := AImgListState; //
64620 fLookTabKeys := [ tkTab ]; //
64621 end; //
64623 //[constructor TControl.CreateTabControl]
64624 constructor TControl.CreateTabControl(AParent: PControl; ATabs: array of String;//
64625 AOptions: TTabControlOptions; //
64626 AImgList: PImageList; AImgList1stIdx: Integer); //
64627 var I, II : Integer; //
64628 Flags: Integer; //
64629 begin //
64630 Flags := MakeFlags( @AOptions, TabControlFlags ); //
64631 if tcoFocusTabs in AOptions then //
64632 Flags := Flags or (WS_TABSTOP or TCS_FOCUSONBUTTONDOWN); //
64633 CreateCommonControl( AParent, WC_TABCONTROL, //
64634 Flags or (WS_CHILD or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or //
64635 WS_VISIBLE), True, @TabControlActions ); //
64636 if not( tcoBorder in AOptions ) then //
64637 fExStyle := fExStyle and not WS_EX_CLIENTEDGE; //
64638 AttachProc( WndProcTabControl ); //
64639 with fBoundsRect do //
64640 begin //
64641 Right := Left + 100; //
64642 Bottom := Top + 100; //
64643 end; //
64644 if AImgList <> nil then //
64645 Perform( TCM_SETIMAGELIST, 0, AImgList.Handle ); //
64646 II := AImgList1stIdx; //
64647 for I := 0 to High( ATabs ) do //
64648 begin //
64649 TC_Insert( I, ATabs[ I ], II ); //
64650 Inc( II ); //
64651 end; //
64652 fLookTabKeys := [ tkTab ]; //
64653 end; //
64655 //[constructor TControl.CreateToolbar]
64656 constructor TControl.CreateToolbar(AParent: PControl; //
64657 AAlign: TControlAlign; AOptions: TToolbarOptions; ABitmap: HBitmap; //
64658 AButtons: array of PChar; ABtnImgIdxArray: array of Integer); //
64659 var Flags: DWORD; //
64660 begin //
64661 if not( tboTextBottom in AOptions ) then //
64662 AOptions := AOptions + [ tboTextRight ]; //
64663 if tboTextRight in AOptions then //
64664 AOptions := AOptions - [ tboTextBottom ]; //
64665 Flags := MakeFlags( @AOptions, ToolbarOptions ); //
64666 CreateCommonControl( AParent, TOOLBARCLASSNAME, ToolbarAligns[ Align ] or //
64667 WS_CHILD or WS_VISIBLE {or WS_TABSTOP} //
64668 or TBSTYLE_TOOLTIPS or Flags, //
64669 (not (Align in [caNone])) and //
64670 not (tboNoDivider in AOptions), nil ); //
64671 fCommandActions.aClear := ClearToolbar; //
64672 fCommandActions.aGetCount := TB_BUTTONCOUNT; //
64673 with fBoundsRect do //
64674 begin //
64675 if AAlign in [ caNone ] then //
64676 begin //
64677 Bottom := Top + 26; //
64678 Right := Left + 1000; //
64679 end //
64680 else //
64681 begin //
64682 Left := 0; Right := 0; //
64683 Top := 0; Bottom := 0; //
64684 end; //
64685 end; //
64686 Perform(TB_SETEXTENDEDSTYLE, 0, Perform(TB_GETEXTENDEDSTYLE, 0, 0) or //
64687 TBSTYLE_EX_DRAWDDARROWS); //
64689 AttachProc( WndProcToolbarCtrl ); //
64690 Perform( TB_BUTTONSTRUCTSIZE, Sizeof( TTBButton ), 0 ); //
64691 Perform( TB_SETINDENT, fMargin, 0 ); //
64692 with fBoundsRect do //
64693 begin //
64694 if AAlign in [ caLeft, caRight ] then //
64695 Right := Left + 24 //
64696 else if not (AAlign in [caNone]) then //
64697 Bottom := Top + 22; //
64698 end; //
64699 if ABitmap <> 0 then //
64700 TBAddBitmap( ABitmap ); //
64701 TBAddButtons( AButtons, ABtnImgIdxArray ); //
64702 Perform( WM_SIZE, 0, 0 ); //
64703 end; //
64705 //[constructor TImageList.CreateImageList]
64706 constructor TImageList.CreateImageList(POwner: Pointer); //
64707 var AOwner: PControl; //
64708 begin //
64709 {*************} DoInitCommonControls( ICC_WIN95_CLASSES ); //
64710 Create; //
64711 FAllocBy := 1; //
64712 FMasked := True; //
64713 if POwner = nil then exit; //
64714 FBkColor := TColor( CLR_NONE );
64715 //ImageList_SetBkColor( FHandle, CLR_NONE );
64717 AOwner := POwner; //
64718 FControl := AOwner; //
64719 fNext := PImageList( AOwner.fImageList ); //
64720 if AOwner.fImageList <> nil then //
64721 PImageList( AOwner.fImageList ).fPrev := @Self; //
64722 AOwner.fImageList := @Self; //
64723 end; //
64725 //[constructor TThread.ThreadCreate]
64726 constructor TThread.ThreadCreate; //
64727 begin //
64728 IsMultiThread := True; //
64729 Create; //
64730 FSuspended := True; //
64731 FHandle := CreateThread( nil, // no security //
64732 0, // the same stack size //
64733 @ThreadFunc, // thread entry point //
64734 @Self, // parameter to pass to ThreadFunc //
64735 CREATE_SUSPENDED, // always SUSPENDED //
64736 FThreadID ); // receive thread ID //
64737 end; //
64739 //[constructor TThread.ThreadCreateEx]
64740 constructor TThread.ThreadCreateEx( const Proc: TOnThreadExecute ); //
64741 begin //
64742 ThreadCreate; //
64743 OnExecute := Proc; //
64744 Resume; //
64745 end; //
64747 {$ENDIF USE_CONSTRUCTORS} //****************************************************//
64750 { TCABFile }
64752 //[function OpenCABFile]
64753 function OpenCABFile( const APaths: array of String ): PCABFile;
64754 var I: Integer;
64755 begin
64757 New( Result, Create );
64758 {+}{++}(*Result := PCABFile.Create;*){--}
64759 Result.FSetupapi := LoadLibrary( 'setupapi.dll' );
64760 Result.FNames := NewStrList;
64761 Result.FPaths := NewStrList;
64762 for I := 0 to High( APaths ) do
64763 Result.FPaths.Add( APaths[ I ] );
64764 end;
64766 //[destructor TCABFile.Destroy]
64767 destructor TCABFile.Destroy;
64768 begin
64769 FNames.Free;
64770 FPaths.Free;
64771 FTargetPath := '';
64772 if FSetupapi <> 0 then
64773 FreeLibrary( FSetupapi );
64774 inherited;
64775 end;
64777 const
64778 SPFILENOTIFY_FILEINCABINET = $11;
64779 SPFILENOTIFY_NEEDNEWCABINET = $12;
64781 type
64782 PSP_FILE_CALLBACK = function( Context: Pointer; Notification, Param1, Param2: DWORD ): DWORD;
64783 stdcall;
64785 TSetupIterateCabinet = function ( CabinetFile: PChar; Reserved: DWORD;
64786 MsgHandler: PSP_FILE_CALLBACK; Context: Pointer ): Boolean; stdcall;
64787 //external 'setupapi.dll' name 'SetupIterateCabinetA';
64789 TSetupPromptDisk = function (
64790 hwndParent: HWND; // parent window of the dialog box
64791 DialogTitle: PChar; // optional, title of the dialog box
64792 DiskName: PChar; // optional, name of disk to insert
64793 PathToSource: PChar;// optional, expected source path
64794 FileSought: PChar; // name of file needed
64795 TagFile: PChar; // optional, source media tag file
64796 DiskPromptStyle: DWORD; // specifies dialog box behavior
64797 PathBuffer: PChar; // receives the source location
64798 PathBufferSize: DWORD; // size of the supplied buffer
64799 PathRequiredSize: PDWORD // optional, buffer size needed
64800 ): DWORD; stdcall;
64801 //external 'setupapi.dll' name 'SetupPromptForDiskA';
64803 type
64804 TCabinetInfo = packed record
64805 CabinetPath: PChar;
64806 CabinetFile: PChar;
64807 DiskName: PChar;
64808 SetId: WORD;
64809 CabinetNumber: WORD;
64810 end;
64811 PCabinetInfo = ^TCabinetInfo;
64813 TFileInCabinetInfo = packed record
64814 NameInCabinet: PChar;
64815 FileSize: DWORD;
64816 Win32Error: DWORD;
64817 DosDate: WORD;
64818 DosTime: WORD;
64819 DosAttribs: WORD;
64820 FullTargetName: array[0..MAX_PATH-1] of Char;
64821 end;
64822 PFileInCabinetInfo = ^TFileInCabinetInfo;
64824 //[function CABCallback]
64825 function CABCallback( Context: Pointer; Notification, Param1, Param2: DWORD ): DWORD;
64826 stdcall;
64827 var CAB: PCABFile;
64828 CABPath, OldPath: String;
64829 CABInfo: PCabinetInfo;
64830 CABFileInfo: PFileInCabinetInfo;
64831 hr: Integer;
64832 SetupPromptProc: TSetupPromptDisk;
64833 begin
64834 Result := 0;
64835 CAB := Context;
64836 case Notification of
64837 SPFILENOTIFY_NEEDNEWCABINET:
64838 begin
64839 OldPath := CAB.FPaths.Items[ CAB.FCurCAB ];
64840 Inc( CAB.FCurCAB );
64841 if CAB.FCurCAB = CAB.FPaths.Count then
64842 CAB.FPaths.Add( '?' );
64843 CABPath := CAB.FPaths.Items[ CAB.FCurCAB ];
64844 if CABPath = '?' then
64845 begin
64846 if Assigned( CAB.FOnNextCAB ) then
64847 CAB.FPaths.Items[CAB.FCurCAB ] := CAB.FOnNextCAB( CAB );
64848 CABPath := CAB.FPaths.Items[ CAB.FCurCAB ];
64849 if CABPath = '?' then
64850 begin
64851 SetLength( CABPath, MAX_PATH );
64852 CABInfo := Pointer( Param1 );
64853 if CAB.FSetupapi <> 0 then
64854 SetupPromptProc := GetProcAddress( CAB.FSetupapi, 'SetupPromptForDiskA' )
64855 else
64856 SetupPromptProc := nil;
64857 if Assigned( SetupPromptProc ) then
64858 begin
64859 hr := SetupPromptProc( 0, nil, nil, PChar( ExtractFilePath( OldPath ) ),
64860 CABInfo.CabinetFile, nil, 2 {IDF_NOSKIP}, @CabPath[ 1 ], MAX_PATH, nil );
64861 case hr of
64862 0: // success
64863 begin
64864 StrCopy( PChar( Param2 ), PChar( CABPath ) );
64865 Result := 0;
64866 end;
64867 2: // skip file
64868 Result := 0;
64869 else // cancel
64870 Result := ERROR_FILE_NOT_FOUND;
64871 end;
64872 end;
64874 else
64875 begin
64876 StrCopy( PChar( Param2 ), PChar( CABPath ) );
64877 Result := 0;
64878 end;
64879 end;
64880 end;
64881 SPFILENOTIFY_FILEINCABINET:
64882 begin
64883 CABFileInfo := Pointer( Param1 );
64884 if CAB.FGettingNames then
64885 begin
64886 CAB.FNames.Add( CABFileInfo.NameInCabinet );
64887 Result := 2; // FILEOP_SKIP
64889 else
64890 begin
64891 CABPath := CABFileInfo.NameInCabinet;
64892 if Assigned( CAB.FOnFile ) then
64893 begin
64894 if CAB.FOnFile( CAB, CABPath ) then
64895 begin
64896 if ExtractFilePath( CABPath ) = '' then
64897 if CAB.FTargetPath <> '' then
64898 CABPath := CAB.TargetPath + CABPath;
64899 StrCopy( @CABFileInfo.FullTargetName[ 0 ], PChar( CABPath ) );
64900 Result := 1; // FILEOP_DOIT
64902 else
64903 Result := 2
64905 else
64906 begin
64907 if CAB.FTargetPath <> '' then
64908 StrCopy( @CABFileInfo.FullTargetName[ 0 ], PChar( CAB.TargetPath + CABPath ) );
64909 Result := 1;
64910 end;
64911 end;
64912 end;
64913 end;
64914 end;
64916 //[function TCABFile.Execute]
64917 function TCABFile.Execute: Boolean;
64918 var SetupIterateProc: TSetupIterateCabinet;
64919 begin
64920 FCurCAB := 0;
64921 Result := FALSE;
64922 if FSetupapi = 0 then Exit;
64923 SetupIterateProc := GetProcAddress( FSetupapi, 'SetupIterateCabinetA' );
64924 if not Assigned( SetupIterateProc ) then Exit;
64925 Result := SetupIterateProc( PChar( FPaths.Items[ 0 ] ), 0, CABCallback, @Self );
64926 end;
64928 //[function TCABFile.GetCount]
64929 function TCABFile.GetCount: Integer;
64930 begin
64931 GetNames( 0 );
64932 Result := FNames.Count;
64933 end;
64935 //[function TCABFile.GetNames]
64936 function TCABFile.GetNames(Idx: Integer): String;
64937 begin
64938 if FNames.Count = 0 then
64939 begin
64940 FGettingNames := TRUE;
64941 Execute;
64942 FGettingNames := FALSE;
64943 end;
64944 Result := '';
64945 if Idx < FNames.Count then
64946 Result := FNames.Items[ Idx ];
64947 end;
64949 //[function TCABFile.GetPaths]
64950 function TCABFile.GetPaths(Idx: Integer): String;
64951 begin
64952 Result := FPaths.Items[ Idx ];
64953 end;
64955 //[function TCABFile.GetTargetPath]
64956 function TCABFile.GetTargetPath: String;
64957 begin
64958 Result := FTargetPath;
64959 if Result <> '' then
64960 if Result[ Length( Result ) ] <> '\' then
64961 Result := Result + '\';
64962 end;
64964 //[procedure InvalidateExW]
64965 procedure InvalidateExW( Wnd: HWnd );
64966 begin
64967 InvalidateRect( Wnd, nil, TRUE );
64968 Wnd := GetWindow( Wnd, GW_CHILD );
64969 while Wnd <> 0 do
64970 begin
64971 InvalidateExW( Wnd );
64972 Wnd := GetWindow( Wnd, GW_HWNDNEXT );
64973 end;
64974 end;
64976 //[procedure TControl.InvalidateEx]
64977 procedure TControl.InvalidateEx;
64978 begin
64979 if fHandle = 0 then Exit;
64980 InvalidateExW( fHandle );
64981 end;
64983 //[procedure InvalidateNCW]
64984 procedure InvalidateNCW( Wnd: HWnd; Recursive: Boolean );
64985 begin
64986 SendMessage( Wnd, WM_NCPAINT, 1, 0 );
64987 if not Recursive then Exit;
64988 Wnd := GetWindow( Wnd, GW_CHILD );
64989 while Wnd <> 0 do
64990 begin
64991 InvalidateNCW( Wnd, Recursive );
64992 Wnd := GetWindow( Wnd, GW_HWNDNEXT );
64993 end;
64994 end;
64996 //[procedure TControl.InvalidateNC]
64997 procedure TControl.InvalidateNC(Recursive: Boolean);
64998 begin
64999 if fHandle = 0 then Exit;
65000 InvalidateNCW( fHandle, Recursive );
65001 end;
65003 //[procedure TControl.SetClientMargin]
65004 procedure TControl.SetClientMargin(const Index, Value: Integer);
65005 begin
65006 case Index of
65007 1: fClientTop := Value;
65008 2: fClientBottom := Value;
65009 3: fClientLeft := Value;
65010 4: fClientRight := Value;
65011 end;
65012 Global_Align( @Self );
65013 end;
65015 {$IFDEF F_P}
65016 //[function TControl.GetClientMargin]
65017 function TControl.GetClientMargin(const Index: Integer): Integer;
65018 begin
65019 CASE Index OF
65020 1: Result := fClientTop;
65021 2: Result := fClientBottom;
65022 3: Result := fClientLeft;
65023 4: Result := fClientRight;
65024 END;
65025 end;
65026 {$ENDIF F_P}
65028 { TBits }
65030 //[function NewBits]
65031 function NewBits: PBits;
65032 begin
65034 new( Result, Create );
65035 {+}{++}(*Result := PBits.Create;*){--}
65036 Result.fList := NewList;
65037 //Result.fList.fAddBy := 1;
65038 end;
65040 //[procedure TBits.AssignBits]
65041 procedure TBits.AssignBits(ToIdx: Integer; FromBits: PBits; FromIdx,
65042 N: Integer);
65043 var i: Integer;
65044 NewCount: Integer;
65045 begin
65046 if FromIdx >= FromBits.Count then Exit;
65047 if FromIdx + N > FromBits.Count then
65048 N := FromBits.Count - FromIdx;
65049 Capacity := (ToIdx + N + 8) div 8;
65050 NewCount := Max( Count, ToIdx + N - 1 );
65051 fCount := Max( NewCount, fCount );
65052 fList.fCount := (Capacity + 3) div 4;
65053 while ToIdx and $1F <> 0 do
65054 begin
65055 Bits[ ToIdx ] := FromBits.Bits[ FromIdx ];
65056 Inc( ToIdx );
65057 Inc( FromIdx );
65058 Dec( N );
65059 if N = 0 then Exit;
65060 end;
65061 Move( PByte( Integer( FromBits.fList.fItems ) + (FromIdx + 31) div 32 )^,
65062 PByte( Integer( fList.fItems ) + ToIdx div 32 )^, (N + 31) div 32 );
65063 FromIdx := FromIdx and $1F;
65064 if FromIdx <> 0 then
65065 begin // shift data by (Idx and $1F) bits right
65066 for i := ToIdx div 32 to fList.Count-2 do
65067 fList.Items[ i ] := Pointer(
65068 (DWORD( fList.Items[ i ] ) shr FromIdx) or
65069 (DWORD( fList.Items[ i+1 ] ) shl (32 - FromIdx))
65071 fList.Items[ fList.Count-1 ] := Pointer(
65072 DWORD( fList.Items[ fList.Count-1 ] ) shr FromIdx
65074 end;
65075 end;
65077 //[function TBits.Copy]
65078 procedure TBits.Clear;
65079 begin
65080 fList.Clear;
65081 end;
65083 function TBits.Copy(From, BitsCount: Integer): PBits;
65084 var Shift, N: Integer;
65085 FirstItemPtr: Pointer;
65086 begin
65087 Result := NewBits;
65088 if BitsCount = 0 then Exit;
65089 Result.Capacity := BitsCount + 32;
65090 Result.fCount := BitsCount;
65091 Move( fList.fItems[ From shr 5 ], Result.fList.fItems[ 0 ], (Count + 31) div 32 );
65092 Shift := From and $1F;
65093 if Shift <> 1 then
65094 begin
65095 N := (BitsCount + 31) div 32;
65096 FirstItemPtr := @ Result.fList.fItems[ N - 1 ];
65098 PUSH ESI
65099 PUSH EDI
65100 MOV ESI, FirstItemPtr
65101 MOV EDI, ESI
65103 MOV ECX, N
65104 XOR EAX, EAX
65106 @@1:
65107 PUSH ECX
65108 LODSD
65109 MOV ECX, Shift
65110 SHRD EAX, EDX, CL
65111 STOSD
65112 SUB ECX, 32
65113 NEG ECX
65114 SHR EDX, CL
65115 POP ECX
65117 LOOP @@1
65120 POP EDI
65121 POP ESI
65122 end {$IFDEF F_P} ['EAX','EDX','ECX'] {$ENDIF};
65123 end;
65124 end;
65126 //[destructor TBits.Destroy]
65127 destructor TBits.Destroy;
65128 begin
65129 fList.Free;
65130 inherited;
65131 end;
65133 //[function TBits.GetBit]
65134 function TBits.GetBit(Idx: Integer): Boolean;
65135 begin
65136 if Idx >= Count then Result := FALSE else
65137 Result := ( ( DWORD( fList.fItems[ Idx shr 5 ] ) shr (Idx and $1F)) and 1 ) <> 0;
65138 end;
65140 //[function TBits.GetCapacity]
65141 function TBits.GetCapacity: Integer;
65142 begin
65143 Result := fList.Capacity * 32;
65144 end;
65146 //[function TBits.GetSize]
65147 function TBits.GetSize: Integer;
65148 begin
65149 Result := (fList.fCount + 3) div 4;
65150 end;
65152 {$IFDEF ASM_noVERSION}
65153 //[function TBits.IndexOf]
65154 function TBits.IndexOf(Value: Boolean): Integer;
65155 asm //cmd //opd
65156 PUSH EDI
65157 MOV EDI, [EAX].fList
65158 MOV ECX, [EDI].TList.fCount
65159 @@ret_1:
65160 OR EAX, -1
65161 JECXZ @@ret_EAX
65162 MOV EDI, [EDI].TList.fItems
65163 TEST DL, DL
65164 MOV EDX, EDI
65165 JE @@of_false
65166 INC EAX
65167 REPZ SCASD
65168 JE @@ret_1
65169 MOV EAX, [EDI-4]
65170 NOT EAX
65171 JMP @@calc_offset
65172 BSF EAX, EAX
65173 SUB EDI, EDX
65174 SHR EDI, 2
65175 ADD EAX, EDI
65176 JMP @@ret_EAX
65177 @@of_false:
65178 REPE SCASD
65179 JE @@ret_1
65180 MOV EAX, [EDI-4]
65181 @@calc_offset:
65182 BSF EAX, EAX
65183 DEC EAX
65184 SUB EDI, 4
65185 SUB EDI, EDX
65186 SHL EDI, 3
65187 ADD EAX, EDI
65188 @@ret_EAX:
65189 POP EDI
65190 end;
65191 {$ELSE ASM_VERSION} //Pascal
65192 function TBits.IndexOf(Value: Boolean): Integer;
65193 var I: Integer;
65194 D: DWORD;
65195 begin
65196 Result := -1;
65197 if Value then
65198 begin
65199 for I := 0 to fList.Count-1 do
65200 begin
65201 D := DWORD( fList.fItems[ I ] );
65202 if D <> 0 then
65203 begin
65205 MOV EAX, D
65206 BSF EAX, EAX
65207 MOV D, EAX
65208 end {$IFDEF F_P} [ 'EAX' ] {$ENDIF};
65209 Result := I * 32 + Integer( D );
65210 break;
65211 end;
65212 end;
65214 else
65215 begin
65216 for I := 0 to fList.fCount-1 do
65217 begin
65218 D := DWORD( fList.fItems[ I ] );
65219 if D <> $FFFFFFFF then
65220 begin
65222 MOV EAX, D
65223 NOT EAX
65224 BSF EAX, EAX
65225 MOV D, EAX
65226 end {$IFDEF F_P} [ 'EAX' ] {$ENDIF};
65227 Result := I * 32 + Integer( D );
65228 break;
65229 end;
65230 end;
65231 end;
65232 end;
65233 {$ENDIF ASM_VERSION}
65235 //[function TBits.LoadFromStream]
65236 function TBits.LoadFromStream(strm: PStream): Integer;
65238 i: Integer;
65239 begin
65240 Result := strm.Read( i, 4 );
65241 if Result < 4 then Exit;
65243 bits[ i]:= false; //by miek
65244 fcount:= i;
65246 i := (i + 7) div 8;
65247 Inc( Result, strm.Read( fList.fItems^, i ) );
65248 end;
65250 //[function TBits.OpenBit]
65251 function TBits.OpenBit: Integer;
65252 begin
65253 Result := IndexOf( FALSE );
65254 if Result < 0 then Result := Count;
65255 end;
65257 //[function TBits.Range]
65258 function TBits.Range(Idx, N: Integer): PBits;
65259 begin
65260 Result := NewBits;
65261 Result.AssignBits( 0, @ Self, Idx, N );
65262 end;
65264 //[function TBits.SaveToStream]
65265 function TBits.SaveToStream(strm: PStream): Integer;
65266 begin
65267 Result := strm.Write( fCount, 4 );
65268 if fCount = 0 then Exit;
65269 Inc( Result, strm.Write( fList.fItems^, (fCount + 7) div 8 ) );
65270 end;
65272 //[procedure TBits.SetBit]
65273 procedure TBits.SetBit(Idx: Integer; const Value: Boolean);
65274 var Msk: DWORD;
65275 begin
65276 if Idx >= Capacity then
65277 Capacity := Idx + 1;
65278 Msk := 1 shl (Idx and $1F);
65279 if Value then
65280 fList.fItems[ Idx shr 5 ] := Pointer(
65281 DWORD(fList.fItems[ Idx shr 5 ]) or Msk)
65282 else
65283 fList.fItems[ Idx shr 5 ] := Pointer(
65284 DWORD(fList.fItems[ Idx shr 5 ]) and not Msk);
65285 if Idx >= fCount then
65286 fCount := Idx + 1;
65287 end;
65289 //[procedure TBits.SetCapacity]
65290 procedure TBits.SetCapacity(const Value: Integer);
65291 var OldCap: Integer;
65292 begin
65293 OldCap := fList.Capacity;
65294 fList.Capacity := (Value + 31) div 32;
65295 if OldCap < fList.Capacity then
65296 FillChar( PChar( Integer( fList.fItems ) + OldCap * Sizeof( Pointer ) )^,
65297 (fList.Capacity - OldCap) * sizeof( Pointer ), 0 );
65298 end;
65300 { ----------------------------------------------------------------------
65302 TAction and TActionList
65304 ----------------------------------------------------------------------- }
65305 //[function NewActionList]
65306 function NewActionList(AOwner: PControl): PActionList;
65307 begin
65309 New( Result, Create );
65310 {+} {++}(* Result := PActionList.Create; *){--}
65311 with Result{-}^{+} do begin
65312 FActions:=NewList;
65313 FOwner:=AOwner;
65314 RegisterIdleHandler(DoUpdateActions);
65315 end;
65316 end;
65317 //[END NewActionList]
65319 //[function NewAction]
65320 function NewAction(const ACaption, AHint: string; AOnExecute: TOnEvent): PAction;
65321 begin
65323 New( Result, Create );
65324 {+} {++}(* Result := PAction.Create; *){--}
65325 with Result{-}^{+} do begin
65326 FControls:=NewList;
65327 Enabled:=True;
65328 Visible:=True;
65329 Caption:=ACaption;
65330 Hint:=AHint;
65331 OnExecute:=AOnExecute;
65332 end;
65333 end;
65334 //[END NewAction]
65336 { TAction }
65338 //[procedure TAction.LinkCtrl]
65339 procedure TAction.LinkCtrl(ACtrl: PObj; ACtrlKind: TCtrlKind; AItemID: integer; AUpdateProc: TOnUpdateCtrlEvent);
65341 cr: PControlRec;
65342 begin
65343 New(cr);
65344 with cr^ do begin
65345 Ctrl:=ACtrl;
65346 CtrlKind:=ACtrlKind;
65347 ItemID:=AItemID;
65348 UpdateProc:=AUpdateProc;
65349 end;
65350 FControls.Add(cr);
65351 AUpdateProc(cr);
65352 end;
65354 //[procedure TAction.LinkControl]
65355 procedure TAction.LinkControl(Ctrl: PControl);
65356 begin
65357 LinkCtrl(Ctrl, ckControl, 0, UpdateCtrl);
65358 Ctrl.OnClick:=DoOnControlClick;
65359 end;
65361 //[procedure TAction.LinkMenuItem]
65362 procedure TAction.LinkMenuItem(Menu: PMenu; MenuItemIdx: integer);
65363 {$IFDEF _FPC}
65365 arr1_DoOnMenuItem: array[ 0..0 ] of TOnMenuItem;
65366 {$ENDIF _FPC}
65367 begin
65368 LinkCtrl(Menu, ckMenu, MenuItemIdx, UpdateMenu);
65369 {$IFDEF _FPC}
65370 arr1_DoOnMenuItem[ 0 ] := DoOnMenuItem;
65371 Menu.AssignEvents(MenuItemIdx, arr1_DoOnMenuItem);
65372 {$ELSE}
65373 Menu.AssignEvents(MenuItemIdx, [ DoOnMenuItem ]);
65374 {$ENDIF}
65375 end;
65377 //[procedure TAction.LinkToolbarButton]
65378 procedure TAction.LinkToolbarButton(Toolbar: PControl; ButtonIdx: integer);
65379 {$IFDEF _FPC}
65381 arr1_DoOnToolbarButtonClick: array[ 0..0 ] of TOnToolbarButtonClick;
65382 {$ENDIF _FPC}
65383 begin
65384 LinkCtrl(Toolbar, ckToolbar, ButtonIdx, UpdateToolbar);
65385 {$IFDEF _FPC}
65386 arr1_DoOnToolbarButtonClick[ 0 ] := DoOnToolbarButtonClick;
65387 Toolbar.TBAssignEvents(ButtonIdx, arr1_DoOnToolbarButtonClick);
65388 {$ELSE}
65389 Toolbar.TBAssignEvents(ButtonIdx, [DoOnToolbarButtonClick]);
65390 {$ENDIF}
65391 end;
65393 //[destructor TAction.Destroy]
65394 destructor TAction.Destroy;
65395 begin
65396 FControls.Release;
65397 FCaption:='';
65398 FShortCut:='';
65399 FHint:='';
65400 inherited;
65401 end;
65403 //[procedure TAction.DoOnControlClick]
65404 procedure TAction.DoOnControlClick(Sender: PObj);
65405 begin
65406 Execute;
65407 end;
65409 //[procedure TAction.DoOnMenuItem]
65410 procedure TAction.DoOnMenuItem(Sender: PMenu; Item: Integer);
65411 begin
65412 Execute;
65413 end;
65415 //[procedure TAction.DoOnToolbarButtonClick]
65416 procedure TAction.DoOnToolbarButtonClick(Sender: PControl; BtnID: Integer);
65417 begin
65418 Execute;
65419 end;
65421 //[procedure TAction.Execute]
65422 procedure TAction.Execute;
65423 begin
65424 if Assigned(FOnExecute) and FEnabled then
65425 FOnExecute(PObj( @Self ));
65426 end;
65428 //[procedure TAction.SetCaption]
65429 procedure TAction.SetCaption(const Value: string);
65431 i: integer;
65432 c, ss: string;
65434 begin
65435 i:=Pos(#9, Value);
65436 if i <> 0 then begin
65437 c:=Copy(Value, 1, i - 1);
65438 ss:=Copy(Value, i + 1, MaxInt);
65440 else begin
65441 c:=Value;
65442 ss:='';
65443 end;
65444 if (FCaption = c) and (FShortCut = ss) then exit;
65445 FCaption:=c;
65446 FShortCut:=ss;
65447 UpdateControls;
65448 end;
65450 //[procedure TAction.SetChecked]
65451 procedure TAction.SetChecked(const Value: boolean);
65452 begin
65453 if FChecked = Value then exit;
65454 FChecked := Value;
65455 UpdateControls;
65456 end;
65458 //[procedure TAction.SetEnabled]
65459 procedure TAction.SetEnabled(const Value: boolean);
65460 begin
65461 if FEnabled = Value then exit;
65462 FEnabled := Value;
65463 UpdateControls;
65464 end;
65466 //[procedure TAction.SetHelpContext]
65467 procedure TAction.SetHelpContext(const Value: integer);
65468 begin
65469 if FHelpContext = Value then exit;
65470 FHelpContext := Value;
65471 UpdateControls;
65472 end;
65474 //[procedure TAction.SetHint]
65475 procedure TAction.SetHint(const Value: string);
65476 begin
65477 if FHint = Value then exit;
65478 FHint := Value;
65479 UpdateControls;
65480 end;
65482 //[procedure TAction.SetOnExecute]
65483 procedure TAction.SetOnExecute(const Value: TOnEvent);
65484 begin
65485 if @FOnExecute = @Value then exit;
65486 FOnExecute:=Value;
65487 UpdateControls;
65488 end;
65490 //[procedure TAction.SetVisible]
65491 procedure TAction.SetVisible(const Value: boolean);
65492 begin
65493 if FVisible = Value then exit;
65494 FVisible := Value;
65495 UpdateControls;
65496 end;
65498 //[procedure TAction.UpdateControls]
65499 procedure TAction.UpdateControls;
65501 i: integer;
65502 begin
65503 with FControls{-}^{+} do
65504 for i:=0 to Count - 1 do
65505 PControlRec(Items[i]).UpdateProc(Items[i]);
65506 end;
65508 //[procedure TAction.UpdateCtrl]
65509 procedure TAction.UpdateCtrl(Sender: PControlRec);
65510 begin
65511 with Sender^, PControl(Ctrl){-}^{+} do begin
65512 if Caption <> Self.FCaption then
65513 Caption:=Self.FCaption;
65514 if Enabled <> Self.FEnabled then
65515 Enabled:=Self.FEnabled;
65516 if Checked <> Self.FChecked then
65517 Checked:=Self.FChecked;
65518 if Visible <> Self.FVisible then
65519 Visible:=Self.FVisible;
65520 end;
65521 end;
65523 //[procedure TAction.UpdateMenu]
65524 procedure TAction.UpdateMenu(Sender: PControlRec);
65526 s: string;
65527 begin
65528 with Sender^, PMenu(Ctrl).Items[ItemID]{-}^{+} do begin
65529 s:=Self.FCaption;
65530 if Self.FShortCut <> '' then
65531 s:=s + #9 + Self.FShortCut;
65532 if Caption <> s then
65533 Caption:=s;
65534 if Enabled <> Self.FEnabled then
65535 Enabled:=Self.FEnabled;
65536 if Checked <> Self.FChecked then
65537 Checked:=Self.FChecked;
65538 if Visible <> Self.FVisible then
65539 Visible:=Self.FVisible;
65540 if HelpContext <> Self.FHelpContext then
65541 HelpContext:=Self.FHelpContext;
65542 if Self.FAccelerator.Key <> 0 then {YS} // Äîáàâèòü
65543 Accelerator:=Self.FAccelerator;
65544 end;
65545 end;
65547 //[procedure TAction.UpdateToolbar]
65548 procedure TAction.UpdateToolbar(Sender: PControlRec);
65550 i: integer;
65551 s: string;
65552 begin
65553 with Sender^, PControl(Ctrl){-}^{+} do begin
65554 i:=TBIndex2Item(ItemID);
65555 s:=TBButtonText[i];
65556 if (s <> '') and (s <> Self.FCaption) then
65557 TBButtonText[i]:=Self.FCaption;
65558 TBSetTooltips(i, [PChar(Self.FHint)]);
65559 if TBButtonEnabled[ItemID] <> Self.FEnabled then
65560 TBButtonEnabled[ItemID]:=Self.FEnabled;
65561 if TBButtonVisible[ItemID] <> Self.FVisible then
65562 TBButtonVisible[ItemID]:=Self.FVisible;
65563 if TBButtonChecked[ItemID] <> Self.FChecked then
65564 TBButtonChecked[ItemID]:=Self.FChecked;
65565 end;
65566 end;
65568 //[procedure TAction.SetAccelerator]
65569 procedure TAction.SetAccelerator(const Value: TMenuAccelerator);
65570 begin
65571 if (FAccelerator.fVirt = Value.fVirt) and (FAccelerator.Key = Value.Key) then exit;
65572 FAccelerator := Value;
65573 FShortCut:=GetAcceleratorText(FAccelerator); // {YS}
65574 UpdateControls;
65575 end;
65577 { TActionList }
65579 //[function TActionList.Add]
65580 function TActionList.Add(const ACaption, AHint: string; OnExecute: TOnEvent): PAction;
65581 begin
65582 Result:=NewAction(ACaption, AHint, OnExecute);
65583 FActions.Add(Result);
65584 end;
65586 //[procedure TActionList.Clear]
65587 procedure TActionList.Clear;
65588 begin
65589 while FActions.Count > 0 do
65590 Delete(0);
65591 FActions.Clear;
65592 end;
65594 //[procedure TActionList.Delete]
65595 procedure TActionList.Delete(Idx: integer);
65596 begin
65597 Actions[Idx].Free;
65598 FActions.Delete(Idx);
65599 end;
65601 //[destructor TActionList.Destroy]
65602 destructor TActionList.Destroy;
65603 begin
65604 UnRegisterIdleHandler(DoUpdateActions);
65605 Clear;
65606 FActions.Free;
65607 inherited;
65608 end;
65610 //[procedure TActionList.DoUpdateActions]
65611 procedure TActionList.DoUpdateActions(Sender: PObj);
65612 begin
65613 if Assigned(FOnUpdateActions) and (GetActiveWindow = FOwner.Handle) then
65614 FOnUpdateActions(PObj( @Self ));
65615 end;
65617 //[function TActionList.GetActions]
65618 function TActionList.GetActions(Idx: integer): PAction;
65619 begin
65620 Result:=FActions.Items[Idx];
65621 end;
65623 //[function TActionList.GetCount]
65624 function TActionList.GetCount: integer;
65625 begin
65626 Result:=FActions.Count;
65627 end;
65629 {$IFDEF USE_CUSTOMEXTENSIONS}
65630 {$I CUSTOM_CODE_EXTENSION.inc} // See comments in TControl
65631 {$ENDIF USE_CUSTOMEXTENSIONS}
65633 //[initialization]
65634 initialization
65635 //[finalization]
65636 finalization
65637 {$IFDEF UNLOAD_RICHEDITLIB}
65638 if FRichEditModule <> 0 then
65639 FreeLibrary( FRichEditModule );
65640 {$ENDIF UNLOAD_RICHEDITLIB}
65642 //[END OF KOL.pas]
65643 end.